我们主要是从配置类入手.
@Configuration@ComponentScan(basePackages="suibibk")@EnableTransactionManagementpublic 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 violationprivate 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中,首先使用被标注的DataSourcepublic DataSource dataSource() {DruidDataSource datasource = new DruidDataSource();datasource.setUrl(this.dbUrl);datasource.setUsername(username);datasource.setPassword(password);datasource.setDriverClassName(driverClassName);//configurationdatasource.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;}@Beanpublic JdbcTemplate jdbcTemplate(DataSource datasource) {return new JdbcTemplate(datasource);}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}}
其实看过AOP源码的都知道,事务远比AOP简单的多,我们首先找到开启事务的关键注解
@EnableTransactionManagement
点进去发现
@Import(TransactionManagementConfigurationSelector.class)
而我们知道TransactionManagementConfigurationSelector实现了ImportSelector接口,所以会制动调用它的selectImports方法,返回对象
@Overrideprotected 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;}}
也就是会生成如下连个对象
AutoProxyRegistrarProxyTransactionManagementConfiguration
我们一个个来分析
一、AutoProxyRegistrar
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar
我们很熟悉,之前AOP也是跟这个一样的,再解析完配置类后会调用这个对象的registerBeanDefinitions方法,然后注入一个类
@Overridepublic 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);
是不是很熟悉
@Nullablepublic static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);}
最终会加载InfrastructureAdvisorAutoProxyCreator对象,这个是跟AOP的AnnotationAwareAspectJAutoProxyCreator一个级别的,那后面代码的跟中也很明确了,当然是直接找
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
和
@Overridepublic 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)
这三个操作事务的方法。
我们在配置文件配置的是
@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
所以我猜想,我们后面的事务操作都会由DataSourceTransactionManager来完成
dataSource : DataSourceenforceReadOnly : booleanDataSourceTransactionManager()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,然后放到缓存的行为
@Overridepublic 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没有重写这个方法,所以不在这里操作,我们可以直接看
@Overridepublic 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@Nullableprotected 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:BeanFactoryTransactionAttributeSourceAdvisoradvisorNames = 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是怎么执行的,事务又是怎么执行的。
