1、解析配置文件
1.1 、解析配置文件的阶段
处理配置文件是在 refresh => invokeBeanFactoryPostProcessors ,即在调用 BeanFactory后置处理器阶段 对配置文件进行解析。
其中有个ConfigurationClassPostProcessor 类,该类是BeanDefinitionRegistryPostProcessor接口类型,该接口定义了注册BeanDefinition的规范。
在 postProcessBeanDefinitionRegistry方法中创建ConfigurationClassParser对象,调用其parse方法来解析配置文件并注册相关的BeanDefinition。
⭐️ 关键点⭐️
refresh => invokeBeanFactoryPostProcessors
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
ConfigurationClassPostProcessor #postProcessBeanDefinitionRegistry
ConfigurationClassParser#.parse
1.2、解析配置文件的方式
具体的解析在解析过程是循环递归的,即会解析配置文件的注解,解析注解的注解…, 层层递归。
1.3、案例解析
首先看看递归解析注解的调用栈:
collectImports:525, ConfigurationClassParser (org.springframework.context.annotation) [2]
collectImports:520, ConfigurationClassParser (org.springframework.context.annotation) [1]
getImports:496, ConfigurationClassParser (org.springframework.context.annotation)
----------------------------------------------------------------------------------------------------
doProcessConfigurationClass:287, ConfigurationClassParser (org.springframework.context.annotation)
processConfigurationClass:226, ConfigurationClassParser (org.springframework.context.annotation)
parse:181, ConfigurationClassParser (org.springframework.context.annotation)
parse:149, ConfigurationClassParser (org.springframework.context.annotation)
processConfigBeanDefinitions:304, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:220, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:290, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:89, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:703, AbstractApplicationContext (org.springframework.context.support)
refresh:520, AbstractApplicationContext (org.springframework.context.support)
main:17, TXSpringTest (com.yh.stu.spring.annotation.tx)
(1)找到配置类TXConf(processConfigBeanDefinitions:304)
(2)解析配置类(parse:149),
(3)循环递归找到@EnableTransactionManagement注解的注解@Import(TransactionManagementConfigurationSelector.class)
(4)
while TXConf 的配置{//1-processConfigurationClass
//2-doProcessConfigurationClass
@Component
@ropertySource
@ComponentScan{
//1-processConfigurationClass
while OrderDao 的配置{
@Component
@ropertySource
@ComponentScan{
空
}
for 递归 @Import 注解{
}
}
}
@Import{
for递归收集注解中@Import导入的类,放入set中{
......
}
例: (TXConf.java)事务配置TXConf的注解@EnableTransactionManagement的注解@Import(TransactionManagementConfigurationSelector.class)
processImports方法for循环处理set中的3种类{
1、ImportSelector类型的类
事务示例:TransactionManagementConfigurationSelector,实例化该类,然后调用它的接口方法selectImports,返回2个类名称的数组:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
递归调用processImports方法,处理AutoProxyRegistrar、ProxyTransactionManagementConfiguration
2、ImportBeanDefinitionRegistrar类型的类
事务示例:AutoProxyRegistrar是这个类型的类,创建类对象,将其放入配置类TXConf包装类ConfigurationClass的Map属性中
3、非以上两种类型
事务示例:ProxyTransactionManagementConfiguration就是该类型,此时把该类当做类似TXConf的普通的配置类,以上所有的处理流程都要针对其进行处理。所以说整个配置文件的解析过程是个 “递归解析的过程”
}
}
@ImportResource
@Bean
}
⭐️总结一下:
1、Spring中类似TXConf的配置文件是可以有多个的,while解析多个配置文件
2、处理@Import注解导入的类过程存在递归调用,分别是1、3两种类型,1递归processImports方法 、3递归processConfigurationClass方法
2、解析 ProxyTransactionManagementConfiguration ,得到4个类
上一节分析了配置文件的解析过程,我们这里把 ProxyTransactionManagementConfiguration 配置文件的解析过程独立出来分析,因为本类主要是和事务相关的内容。
我们看ProxyTransactionManagementConfiguration 的源码,都是通过@Bean标注的方法进行Bean的注册
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
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() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
return new TransactionalEventListenerFactory();
}
}
⭐️ 解析出了4个类 :
1、BeanFactoryTransactionAttributeSourceAdvisor
2、AnnotationTransactionAttributeSource
3、TransactionInterceptor
4、TransactionalEventListenerFactory (父类)
3、注册BeanDefinition
解析完配置后,一切准备就绪,每个配置文件都会被封装为ConfigurationClass,此时new 一个ConfigurationClassBeanDefinitionReader对象,调用 loadBeanDefinitions(configClasses)。
一般情况下ConfigurationClass对象有多个,包括用户@Configuration配置的,还有配置文件中@ComponentScan扫描的,@Import注解中 “导入”的带@Configuration注解的。
loadBeanDefinitions for循环遍历多个ConfigurationClass
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
SS.l("注册"+SS.sn(configClass.getBeanName())+" 配置类本身的 BeanDefinition.");
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
上文提到了
【事务示例:
AutoProxyRegistrar是ImportBeanDefinitionRegistrar类型的类,创建类的对象,将其放入配置类TXConf包装类ConfigurationClass的Map属性中】
在最后一步,loadBeanDefinitionsFromRegistrars方法中会处理,AutoProxyRegistrar 的registerBeanDefinitions 方法中会注册InfrastructureAdvisorAutoProxyCreator,该类BeanPostProcessor接口的实现类。
3、创建Bean - BeanFactoryTransactionAttributeSourceAdvisor
创建TXConf实例时(doCreateBean(..)),initializeBean(..)方法对其进行初始化, for 循环遍历所有的BeanPostProcessor{
调用InfrastructureAdvisorAutoProxyCreator.postProcessAfterInitialization(..){
wrapIfNecessary(..){// 对TXConf实例尝试创建代理对象
从BeanFactory中找出所有的Advisor,发现BeanFactoryTransactionAttributeSourceAdvisor的 Bean 还没有创建该
创建 BeanFactoryTransactionAttributeSourceAdvisor 的Bean{
调用 ProxyTransactionManagementConfiguration#transactionAdvisor创建BeanFactoryTransaction???Advisor
// 注意:BeanFactoryTransactionAttributeSourceAdvisor 是通过 @Bean 方法创建的,transactionAdvisor方法中还调用了
// 其他两个方法
}
}
}
}
方法 ProxyTransactionManagementConfiguration#transactionAdvisor
如下:
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
4、用 InfrastructureAdvisorAutoProxyCreator 创建代理对象
在创建OrderSerivceImpl对象后,对象进行初始化(AbstractAutowireCapableBeanFactory#initializeBean)。
调用 InfrastructureAdvisorAutoProxyCreator(BeanPostProcessor类型 )的 applyBeanPostProcessorsAfterInitialization 方法,方法中调用对需要代理的对象进行创建代理对象(AbstractAutoProxyCreator#wrapIfNecessary)
wrapIfNecessary:342, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
postProcessAfterInitialization:293, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:385, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1740, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:551, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:471, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:277, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 854507466 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$12)
getSingleton:211, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:275, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:155, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:802, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:876, AbstractApplicationContext (org.springframework.context.support)
refresh:544, AbstractApplicationContext (org.springframework.context.support)
main:17, TXSpringTest (com.yh.stu.spring.annotation.tx)
4.1、获取Bean的Advisor
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean
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;
}
findCandidateAdvisors()方法会找出所有的 Advisor 对象,包括 BeanFactoryTransactionAttributeSourceAdvisor 类的对象
findAdvisorsThatCanApply方法找出Bean适用的Advisor对象,比如 BeanFactoryTransactionAttributeSourceAdvisor 类的对象
4.2、createProxy 创建代理对象
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//确定给定bean的advisor,包括特定的拦截器和通用的拦截器,所有这些都是Advisor接口的实现类。
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
ProxyFactory#getProxy方法返回 DefaultAopProxyFactory 类型的对象
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
DefaultAopProxyFactory#createAopProxy 方法 返回 JdkDynamicAopProxy 或 ObjenesisCglibAopProxy,参考
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
5、调用加了@Transaction 注解的方法
TransactionAspectSupport#invokeWithinTransaction
invokeWithinTransaction:286, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:98, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:209, JdkDynamicAopProxy (org.springframework.aop.framework)
queryAll:-1, $Proxy22 (com.sun.proxy)
main:18, TXSpringTest (com.yh.stu.spring.annotation.tx)
说说事务未生效的几种情况?
为什么我的事务不生效
1.如果不是Innodb存储引擎,MyISAM不支持事务。
2.没有指定rollbackFor参数。
3. 没有指定transactionManager参数,默认的transactionManager并不是我期望的,以及一个事务中涉及到了多个数据库。
4. 如果AOP使用了JDK动态代理,对象内部方法互相调用不会被Spring的AOP拦截,@Transactional注解无效。
5. 如果AOP使用了CGLIB代理,事务方法或者类不是public,无法被外部包访问到,或者是final无法继承,@transactional注解无效。