Spring注解开发
今天来学习AOP原理。
我们上篇文章已经描述了AOP的使用情况,现在来研究一下AOP的原理。首先从@EnableAspectJAutoProxy注解开始。
@EnableAspectJAutoProxy
1)点击@EnableAspectJAutoProxy注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy
发现,使用了@Import注解来注入组件。组件是AspectJAutoProxyRegistrar类。
2)点击AspectJAutoProxyRegistrar类:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar{
···
}
该类,实现了ImportBeanDefinitionRegistrar接口,说明是用来自定义注入组件的。其中有一个registerBeanDefinitions()方法。
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
查看其中的AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
最终会调用registerOrEscalateApcAsRequired方法:
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
最后是给容器注入了一个Bean:
id:internalAutoProxyCreator ==》 Class:AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
@EnableAspectJAutoProxy注解帮我们注入了AnnotationAwareAspectJAutoProxyCreator组件,这个组件有什么作用呢?
我们观察一下AnnotationAwareAspectJAutoProxyCreator的继承关系:
AnnotationAwareAspectJAutoProxyCreator
AspectJAwareAdvisorAutoProxyCreator
AbstractAdvisorAutoProxyCreator
AbstractAutoProxyCreator
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
关键:实现了两个接口,一个后置处理器(在Bean初始化完成前后做事情)、一个自动装配BeanFactory
调试
打上断点:(与后置处理器,自动装配有关的)
1)AbstractAutoProxyCreator.setBeanFactory
2)AbstractAutoProxyCreator.postProcessBeforeInstantiation
3) AbstractAutoProxyCreator.postProcessAfterInitialization
4) AbstractAdvisorAutoProxyCreator.setBeanFactory(父类重写的方法也打上断点)
5)AbstractAdvisorAutoProxyCreator.initBeanFactory
6) AspectJAwareAdvisorAutoProxyCreator类没有相关的就不打上断点
7)AnnotationAwareAspectJAutoProxyCreator.initBeanFactory(父类重写的方法也打上断点)
8) MainConfigOfAOP配置类的中的两个Bean对象打上断点:
mathCalculator和logAspects
debug
流程:
1)传入配置类,创建IoC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
2) 注册配置类,调用refresh(), 刷新容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses); //注入配置类
refresh(); //刷新容器
}
3)registerBeanPostProcessors(beanFactory);注册bean的后置处理器,来拦截bean的初始化操作。
1.先获取IoC容器已经定义了的需要创建对象的所有BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
2.给容器中加别的BeanPostProcessor
3.优先注册实现了PriorityOrdered接口的BeanPostProcessor
4.再注册实现了Ordered接口的BeanPostProcessor
5.注册没有实现优先级接口的BeanPostProcessor
6.注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存到容器中
创建 internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】
1.创建Bean对象
2.populateBean:给bean的属性赋值
3.initializeBean:初始化bean
1.invokeAwareMethods:处理Aware接口的回调:
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
2.applyBeanPostProcessorsBeforeInitialization:执行后置处理器的postProcessor:postProcessBeforeInitialization方法
3.invokeInitMethods:自定义的初始化方法
4.applyBeanPostProcessorsAfterInitialization:执行postProcessor:postProcessAfterInitialization方法
4.BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;
7.把BeanPostProcessor注册到BeanFactory中:beanFactory.addBeanPostProcessor()
以上是创建AnnotationAwareAspectJAutoProxyCreator的过程。
AnnotationAwareAspectJAutoProxyCreator =》InstantiationAwareBeanPostProcessor,而不是 BeanPostProcessor 后置处理器
InstantiationAwareBeanPostProcessor是 postProcessBeforeInstantiation(实例化)
BeanPostProcessor是postProcessBeforeInitialization(初始化)
说明InstantiationAwareBeanPostProcessor后置处理器是 在Bean实例化前后执行
BeanPostProcessor后置处理器是 在Bean对象初始化前后执行
4)finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作,创建剩下的没有创建的Bean组件
1.遍历获取容器中所有的Bean,依次创建对象;getBean(beanName)
getBean()->doGetBean()->getSingleton()->createBean()
2.创建Bean:
1.先从缓存中获取当前的Bean,如果能获取到,说明bean是之前被创建过,直接使用,否则再创建.
只要创建了bean就会被缓存起来。
2.createBean():创建Bean
1.resolveBeforeInstantiation():解析BeanPostProcessors
想让后置处理器在次能返回一个代理对象,如果能返回代理对象就使用,如果不能就继续。
1.后置处理器先尝试返回代理对象
bean=applyBeanPostProcessorsBeforeInstantiation();拿到所有的后置处理器,如果是 InstantiationAwareBeanPostProcessor;就执行postProcessBeforeInstantiation方法
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
2.doCreateBean():真正去创建一个bean实例;和3.6流程一样
AnnotationAwareAspectJAutoProxyCreator[InstantiationAwareBeanPostProcessor]
1) 每一个bean创建之前,调用postProcessBeforeInstantiation()
关心mathCalculator和logAspects
1)判断当前bean是否是在advicedBean中(保存了所有需要增强bean)
2)判断当前bean是否是基础类型的Advice、PointCut、Advisor、AopInfrastructureBean或者是否是切面(@Aspect)
3)是否需要跳过
1)获取候选的增强器(切面里面的通知方法)【List
每一个封装的通知方法的增强器是InstantiationModelAwarePointcutAdvisor
判断每一个增强器是否是AspectJPointcutAdvisor类型的;返回true
2)永远返回false
2)创建对象
postProcessAfterInitialization:
return wrapIfNecessary(bean, beanName, cacheKey);//需要包装的情况下
1)获取当前bean的所有增强器(通知方法) Object[] specificInterceptors
1)找到候选的所有增强器(找哪些通知方法是需要切入当前bean方法的)
2)获取到能在bean使用的增强器
3)给增强器排序
2)保存当前bean在advisedBeans中;
3)如果当前bean需要增强,创建当前bean的代理对象
1)获取所有的增强器(通知方法)
2)保存到proxyFactory
3)创建代理对象:Spring自动决定
jdk代理
cglib代理
4)给容器中返回当前组件使用cglib代理的对象
5)以后容器中获取的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程
3)目标方法的执行流程
容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器、目标对象,xxx)
1)CglibAopProxy.intercept();拦截目标方法的执行
2)根据ProxyFactory对象获取将要执行的目标方法拦截器
List
1)List
2)遍历所有的增强器,将其转为Interceptor
3)将增强器转为List
3)如果没有拦截器链,直接执行目标方法
4)如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入,创建一个CglibMethodInvocation对象,并调用
Object retVal = mi.proceed();
5) 拦截器链的触发过程
1)如果没有拦截器执行,就直接执行目标方法,或者拦截器的索引和拦截器数组的个数-1一样大,执行目标方法
2)链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行:
拦截器链的机制,保证通知方法与目标方法的执行顺序.
总结
1)@EnableAspectJAutoProxy注解 开启AOP功能
2)@EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator
3)AnnotationAwareAspectJAutoProxyCreator是一个后置处理器
4)容器的创建流程:
1)registerBeanPostProcessors()注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
2)finishBeanFactoryInitialization():初始化剩下的单实例bean
1)创建业务逻辑组件和切面组件
2)AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
3)组件创建完之后,判断组件是否需要增强。是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件
4) 创建一个代理对象
5)执行目标方法:
1)代理对象执行目标方法
2)CglibAopProxy.Intercept:
1)得到目标方法的拦截器链(增强器包装成拦截器MethodIntercept)
2)利用拦截器的链式机制,依次进入每一个拦截器进行执行;
3)效果:
正常执行:前置通知 -》目标方法 -》后置通知 -》返回通知
出现异常:前置通知 -》目标方法 -》后置通知 -》异常通知