Get into the habit of writing together! This is the 5th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .
Spring's AOP implementation
1. @EnableAspectJAutoProxy enables aspect automatic proxy function
If you want to use AOP, we need to add the @EnableAspectJAutoProxy annotation to the startup class, so start from this annotation
Pay attention to three points
Imported an AspectJAutoProxyRegistrar registration component
@Import(AspectJAutoProxyRegistrar.class)
复制代码
boolean proxyTargetClass() default false; //是否使用CGLB创建代理对象
复制代码
boolean exposeProxy() default false; //是否将代理对象放入ThreadLocal ,如果为true,可以通过 AopContext 获取代理对象
复制代码
See what the AspectJAutoProxyRegistrar component has registered and click in
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
复制代码
Implements the ImportBeanDefinitionRegistrar interface, see the rewritten registerBeanDefinitions method
AnnotationAwareAspectJAutoProxyCreator is registered
See what AnnotationAwareAspectJAutoProxyCreator is
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
It is found that AnnotationAwareAspectJAutoProxyCreator inherits the BeanPostProcessor post processor, that is to say, after SpringIOC initializes each bean, it will execute the implementation class of this BeanPostProcessor, and the rewrite method of postProcessAfterInitialization is in org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
2. Post-processing of bean initialization of AbstractAutoProxyCreator
1. Execute the postProcessAfterInitialization method of the bean post processor
2.过滤无需进行AOP的bean
首先看
Object cacheKey = getCacheKey(bean.getClass(), beanName);
复制代码
跟进
wrapIfNecessary(bean, beanName, cacheKey)
复制代码
`Advice Pointcut Advisor AopInfrastructureBean 这四种类型的bean直接返回原对象,不需要进行AOP
` shouldSkip() 方法留给程序员决定那些bean不需要AOP
如下面这个bean 将不会被AOP代理
@Component(value = "com.sgg.proxy.bean.MyBean.ORIGINAL")
public class MyBean {
@MyAop
public void method()
{
System.out.println("方法执行了");
}
}
复制代码
3.先找advice接口的子类
接下来我们看 getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null) 这个方法
跟进来到 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
跟进 findEligibleAdvisors(beanClass, beanName) 方法
先看 findCandidateAdvisors() 是怎么拿到所有的advice的
跟进来到 org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans()
跟进
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false)
复制代码
注意方法的四个参数
拿到所有类型为 Advisor 的beanName 注意只是名字 如果有父容器,也取出父容器中的实现了Advisor 接口的bean的Name
拿到所有的beanName后,遍历,
判断是不是正在创建中,如果正在创建中,跳过 然后调用 this.beanFactory.getBean(name, Advisor.class) 获取(没有就创建bean),放到集合List advisors 中然后返回 至此,拿到了Spring容器中所有的advisor的子类
4.再找标注@Aspect的切面类
回到org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors
通常我们都是使用@Aspect定义一个切面类,这种就需要通过this.aspectJAdvisorsBuilder.buildAspectJAdvisors()去找
this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
复制代码
从容器中取出所有类型为Object的bean 也就是取出所有的bean
拿到class,判断是否有@Aspect注解
调用 List classAdvisors = this.advisorFactory.getAdvisors(factory) 方法 拿到不同的advisor
首先找到类中所有非定义切入点的方法
看adviceMethodFilter过滤器
如果注解类型是PointCut,返回null
回到getAdvisors方法,拿到所有的非@PonitCut的方法后
调用 getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName) 创建 advisor
至此,所有的advisor查找完毕 进行下一步过滤操作
4.按Class和方法名筛选advisor
回到 findEligibleAdvisors 方法 看如何筛选的
跟进
是不是实现了 IntroductionAdvisor 接口,然后调用 canApply(candidate, clazz) 判断是否能应用
跟进canApply(candidate, clazz) 方法
如果当前advisor 是属于 IntroductionAdvisor ,按Class过滤
如果当前advisor 是属于 PointcutAdvisor
调用 canApply(pca.getPointcut(), targetClass, hasIntroductions) 方法
Advisors that match the bean currently being created are eventually stored in List eligibleAdvisors
After finding all advisors and filtering, create a proxy class
5. Create a proxy class
Back to the org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary method
The process of getting all the advice has been completed, the next step is to create a proxy class, draw a picture, and organize the process