aop启动,自然通知类,必不可少,那么spring是如何解析通知类的呢,目前我们从annotation启动过程中,发现spring只是把我们注册到配置类的@Aspect通知类作为一个普通的bean,实例化保存了起来,但是它的内容并没有发挥作用,或者说,当初始化@Aspect通知类的时候,按照我们配置在MyConfig配置类的顺序,前面的普通bean已经实例化,初始化完毕了,他们是如何通过@Aspect通知类进行自动代理的呢?
本节内容就是找到解析@Aspect的方式。
我们通过@EnableAspectJAutoProxy注解中发现,里面注册了一个后置处理器,AnnotationAwareAspectJAutoProxyCreator类,所以,猜测@Aspect通知类的解析,与它有关,而它的结构,其实较为庞大,我们在之间的创建代理中初步介绍了,所以这里不细说,它的调用重点是beforeInstaniation中,也就是creatBean()过程中触发。
还记得在我们的aop配置中,加入了一个注解:@EnableAspectJAutoProxy,源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
第一个参数,表示的是代理方式,true使用cglib方式,false使用jdk方式,第二个参数表示暴露方式,解决内部调用不能使用代理的场景。重点我们放在注解里面导入了一个类,很关键:AspectjAutoProxyRegistrar类
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//【重点】
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
它作为@Import方式导入,在Configuration...Processor解析配置类的过程中,回解析到该类,而且由于它实现了固定的接口,它并不会被导入BeanFactory中,而是会执行该接口的唯一方法,执行完毕,则把下面AnnotationAwareAspectJAutoProxyCreator注册到BeanFactory中,等待被实例化!
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(...) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
....
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;
}
而refresh()第六步,注册BeanPostProcessor的时候,也进行了getBean()操作,而它为什么没有触发AnnotationAwareAspectJAutoProxyCreator类呢?而是在refresh()第十一步:finishBeanFactoryInitialization()方法中触发?
答案很明显,第六步名字都叫做注册BeanPostProcessor,很明显处理@Aspect通知类的处理器,还在向容器中注册,这个时候处理bean的postProcessor只是最原始的几个,还没有处理通知类的能力,所以只有等待refresh()第六步注册完毕之后,才能在第十一步 实例化单例bean中触发,现在我们直接来到十一步的getBean()中:
一般这个时候都是第一次进行实例化,所以getBean()是不存在的,不存在自然就是:getBean-->doGetBean()---->createBean()
所以来到AbstractAutowireCapableBeanFactory类的createBean()方法中,分为四个步骤,如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
//判断该bean,是否可以被当前加载器修改。
Class> resolvedClass = resolveBeanClass(mbd, beanName); //【1】
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
mbdToUse.prepareMethodOverrides(); //【2】
try {
// 处理器处理!
Object bean = resolveBeforeInstantiation(beanName, mbdToUse); //【3】
if (bean != null) {
return bean;
}
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args); //【4】
return beanInstance;
}
}
这里之前创建普通bean的时候,直接研究了第四步,因为走的是第四步,但是这里我们忽略了第三步,aop的实现就在第三步中,调用了后置处理器,这也是后置处理器AbstractAutoProxyCreator有两对before(),after()方法的原因,有一对是在这里调用的,后缀为Instantiation,而有一对的后缀是Initialization,是在初始化的时候调用:
翻译:instantiation 实例化 ----------- initialization 初始化
好,我们进入第三步:resolveBeforeInstaniation() ,bean实例化之前的解析:
如果该方法返回的是null,那么就等着第四步doCreateBean进行实例化-初始化。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
方法1:determineTargetType()方法,确定给bean定义的目标类型,@Target,区分bean的使用范围,如果不在范围,可以不用处理,
参考:https://www.jianshu.com/p/75e0dea370f5
protected Class> determineTargetType(String beanName, RootBeanDefinition mbd, Class>... typesToMatch) {
Class> targetType = mbd.getTargetType();
if (targetType == null) {
targetType = (mbd.getFactoryMethodName() != null ?
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
resolveBeanClass(mbd, beanName, typesToMatch));
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
mbd.resolvedTargetType = targetType;
}
}
return targetType;
}
方法2:如果目录类型不为空,则触发了实例化之前的处理:现在开始遍历处理器调用进行处理:
protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) { //调用后置处理器
if (bp instanceof InstantiationAwareBeanPostProcessor) { //实例化 aware 明白,意识到,发现
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
我们经典的处理器,自然是AbstractAutoProxyCreator类,它的beforeInstantiation()方法:(我们通过@EnableAspectJAutoProxy注解,注册的一个AnnotationAwareAspectJAutoProxyCreator类的父类,复习一下该类的继承结构:
来到AbstractAutoProxyCreator类中: 注意这里还是的参数是待实例化的beanDefinition。而渐渐入场的是spring aop的@Aspect通知类的解析,
前期在检查该bean,是否已经处理过了,处理过了,就返回null,交给doCreateBean()进行实例化-初始化
下半段出现了TargetSource 代理源,可参考:https://blog.csdn.net/shenchaohao12321/article/details/85538163
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {
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); //要跳过的直接设置为false
return null;
}
}
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;
}
上面方法中,重点是shouldSkip()方法,来到它的子类第三层:AspectAwareAdvisorAutoProxyCreator类中:
protected boolean shouldSkip(Class> beanClass, String beanName) {
//发现 候选 Advisor
List candidateAdvisors = findCandidateAdvisors();
//如果返回的 候选Advisor中的AspectName(通知类的name) 和传入的beanName相同,则返回true
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName); //父类方法,直接返回false
}
第一个方法:findCandidateAdvisors(),到达第二层父类:AnnotationAwareAspectAutoProxyCreator类中:
protected List findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
该方法分为两部分,第一个部分使用父类的find()方法,第二个是使用Builder的build()方法
第一个:AbstractAdvisorAutoProxyCreator 第二层类:
protected List findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
跟入: 结果是什么都没有找到,直接返回一个空集合
public List 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!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>(); //走这里返回了
}
List advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
...
return advisors;
}
第二个:
最后是在BeanFactoryAspectJAdvisorBuilder类中的buildAspectJAdvisors()方法中解析@Aspect:
public List buildAspectJAdvisors() {
List aspectNames = this.aspectBeanNames; //获取切面名字列表
//如果 结果过了,自然此处不为null
if (aspectNames == null) {
synchronized (this) { //双重检查
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List advisors = new ArrayList<>(); //通知集合
aspectNames = new ArrayList<>(); //切面名字列表
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( //寻找所有Object类型的bean定义名字
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) { //遍历所有beanName
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) { //找到@Aspect 注解的bean
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List classAdvisors = this.advisorFactory.getAdvisors(factory); //【★】获得 类中的方法
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}//保存结果,避免重复解析,返回
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}//从缓存中取出Advice by aspectName ,返回,=复制一份
List advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
重点方法: 位于ReflectiveAspectJAdvisorFactory类中,待下一节进行解析
解析完毕之后的结果:
这三个值,代表了我在通知类中设置的三个方法,而不是代表三个通知类,特别注意这三个方法的注入,不是通过上面find()方法返回得到的,而是通过Builder.build()方法获得的。
最后返回false
注意,每一次createBean()都会触发shouldSkip()方法,但是如果保存了AspectName,那么自然就回直接返回结果,不会重复进行解析
参考链接:https://blog.csdn.net/wangwei19871103/article/details/105208217(大佬膜拜)