我们主要是从配置类入手.
@Configuration
@ComponentScan(basePackages="suibibk")
@EnableTransactionManagement
public class MyConfiguration {
private String dbUrl = PropertiesUtil.get("dataSource.url");
private String username =PropertiesUtil.get("dataSource.username");
private String password =PropertiesUtil.get("dataSource.password");
private String driverClassName =PropertiesUtil.get("dataSource.driver");
private int initialSize=Integer.parseInt(PropertiesUtil.get("dataSource.initialSize","5"));
private int minIdle= Integer.parseInt(PropertiesUtil.get("dataSource.minIdle","5"));
private int maxActive= Integer.parseInt(PropertiesUtil.get("dataSource.maxActive","20"));
private int maxWait= Integer.parseInt(PropertiesUtil.get("dataSource.maxWait","60000"));
private int timeBetweenEvictionRunsMillis= Integer.parseInt(PropertiesUtil.get("dataSource.timeBetweenEvictionRunsMillis","60000"));
private int minEvictableIdleTimeMillis= Integer.parseInt(PropertiesUtil.get("dataSource.minEvictableIdleTimeMillis","300000"));
private String validationQuery= PropertiesUtil.get("dataSource.validationQuery","SELECT 1 FROM DUAL");
private boolean testWhileIdle= Boolean.parseBoolean(PropertiesUtil.get("dataSource.testWhileIdle","true"));
private boolean testOnBorrow= Boolean.parseBoolean(PropertiesUtil.get("dataSource.testOnBorrow","false"));
private boolean testOnReturn= Boolean.parseBoolean(PropertiesUtil.get("dataSource.testOnReturn","false"));
private boolean poolPreparedStatements=Boolean.parseBoolean(PropertiesUtil.get("dataSource.poolPreparedStatements","true"));
private int maxPoolPreparedStatementPerConnectionSize= Integer.parseInt(PropertiesUtil.get("dataSource.maxPoolPreparedStatementPerConnectionSize","20"));
//wall, 去掉这个,不然会报sql injection violation
private String filters= PropertiesUtil.get("dataSource.filters","stat,log4j");
private String connectionProperties= PropertiesUtil.get("dataSource.connectionProperties","druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");
@Bean //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的DataSource
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
e.printStackTrace();
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource datasource) {
return new JdbcTemplate(datasource);
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
其实看过AOP源码的都知道,事务远比AOP简单的多,我们首先找到开启事务的关键注解
@EnableTransactionManagement
点进去发现
@Import(TransactionManagementConfigurationSelector.class)
而我们知道TransactionManagementConfigurationSelector实现了ImportSelector接口,所以会制动调用它的selectImports方法,返回对象
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
也就是会生成如下连个对象
AutoProxyRegistrar
ProxyTransactionManagementConfiguration
我们一个个来分析
一、AutoProxyRegistrar
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar
我们很熟悉,之前AOP也是跟这个一样的,再解析完配置类后会调用这个对象的registerBeanDefinitions方法,然后注入一个类
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}
看这行代码
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
是不是很熟悉
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
最终会加载InfrastructureAdvisorAutoProxyCreator对象,这个是跟AOP的AnnotationAwareAspectJAutoProxyCreator一个级别的,那后面代码的跟中也很明确了,当然是直接找
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
和
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
好这里暂时不提,我们先看第二个类干了啥
二、ProxyTransactionManagementConfiguration
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
发现竟然是个配置类,也就是说会向容器中初始化三个bean
1、BeanFactoryTransactionAttributeSourceAdvisor
beanName=org.springframework.transaction.config.internalTransactionAdvisor
牛逼了,这里直接指定Advisor,完全不用跟AOP一样苦逼的扫描所有类,然后借助缓存,这个已经指定了,那么完全不用扫描对象了啊。
2、TransactionAttributeSource
这个暂时不知道用来干啥
3、TransactionInterceptor
事务拦截对象
interceptor.setTransactionManager(this.txManager);
里面设置了我们的事务管理器,而我们的事务管理器是
PlatformTransactionManager
这个接口里面定义了
getTransaction(TransactionDefinition)
commit(TransactionStatus)
rollback(TransactionStatus)
这三个操作事务的方法。
我们在配置文件配置的是
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
所以我猜想,我们后面的事务操作都会由DataSourceTransactionManager来完成
dataSource : DataSource
enforceReadOnly : boolean
DataSourceTransactionManager()
DataSourceTransactionManager(DataSource)
setDataSource(DataSource)
getDataSource()
obtainDataSource()
setEnforceReadOnly(boolean)
isEnforceReadOnly()
afterPropertiesSet()
getResourceFactory()
doGetTransaction()
isExistingTransaction(Object)
doBegin(Object, TransactionDefinition)
doSuspend(Object)
doResume(Object, Object)
doCommit(DefaultTransactionStatus)
doRollback(DefaultTransactionStatus)
doSetRollbackOnly(DefaultTransactionStatus)
doCleanupAfterCompletion(Object)
prepareTransactionalConnection(Connection, TransactionDefinition)
好了,我们现在来看看什么时候会生成事务代理对象吧!
三、生成事务代理对象
前面我们说过最终会加载InfrastructureAdvisorAutoProxyCreator对象,这个是跟AOP的AnnotationAwareAspectJAutoProxyCreator一个级别的,因为并且因为ProxyTransactionManagementConfiguration加载bean的时候,直接指定了BeanFactoryTransactionAttributeSourceAdvisor,也就相当于没有必要进行全局扫描所有Object对象去找Advisor了,所以猜测不会在
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
来做一些找到所有Advisor,然后放到缓存的行为
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
之前AOP是在
shouldSkip(beanClass, beanName)
逻辑来处理的,现在我们的InfrastructureAdvisorAutoProxyCreator没有重写这个方法,所以不在这里操作,我们可以直接看
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
这里是跟AOP一样的,我们直接点进去
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
找到关键代码
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
//1、这里会直接找到我们的bean:BeanFactoryTransactionAttributeSourceAdvisor
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
//这里就直接有内容返回了
return advisors;
}
后面就跟AOP一样生成代理对象了
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
到这里大概脉络就完成了,接下来会写两篇文章分析下代理对象的执行逻辑,看看AOP是怎么执行的,事务又是怎么执行的。