SpringBoot 源码阅读(17):AOP

本文深入探讨了SpringBoot中AOP的实现,主要关注@EnableAspectJAutoProxy注解的自动配置,讲解了AnnotationAwareAspectJAutoProxyCreator如何创建代理,包括JDK和CGLIB两种方式。详细阐述了获取增强方法的过程,以及如何根据方法和类上的注解生成对应的拦截器,最终通过工厂模式生成代理对象。
摘要由CSDN通过智能技术生成

AOP

AOP自动配置如下:

@Configuration
@ConditionalOnClass({
   EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class})
@ConditionalOnProperty(
    prefix = "spring.aop",
    name = {
   "auto"},
    havingValue = "true",
    matchIfMissing = true
)
public class AopAutoConfiguration {
   
    public AopAutoConfiguration() {
   
    }

    @Configuration
    @EnableAspectJAutoProxy(
        proxyTargetClass = true
    )
    @ConditionalOnProperty(
        prefix = "spring.aop",
        name = {
   "proxy-target-class"},
        havingValue = "true",
        matchIfMissing = true
    )
    public static class CglibAutoProxyConfiguration {
   
        public CglibAutoProxyConfiguration() {
   
        }
    }

    @Configuration
    @EnableAspectJAutoProxy(
        proxyTargetClass = false
    )
    @ConditionalOnProperty(
        prefix = "spring.aop",
        name = {
   "proxy-target-class"},
        havingValue = "false",
        matchIfMissing = false
    )
    public static class JdkDynamicAutoProxyConfiguration {
   
        public JdkDynamicAutoProxyConfiguration() {
   
        }
    }
}

里面我们重点关注注解 @EnableAspectJAutoProxy

@Target({
   ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({
   AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
   
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;
}

其引入AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   
    AspectJAutoProxyRegistrar() {
   
    }

    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);
            }
        }

    }
}

首先看下registerAspectJAnnotationAutoProxyCreatorIfNecessary

AnnotationAwareAspectJAutoProxyCreator

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
   
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
   
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
   
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
   
        BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
   
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
   
                apcDefinition.setBeanClassName(cls.getName());
            }
        }

        return null;
    } else {
   
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", -2147483648);
        beanDefinition.setRole(2);
        registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
        return beanDefinition;
    }
}

这一段代码其实就是注册了AnnotationAwareAspectJAutoProxyCreator
在这里插入图片描述
其实现了bean后处理器,在bean实例化前后会对其处理(见博客)。
一层层往上找,在AbstractAutoProxyCreator找到了

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   
    if (bean != null) {
   
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
   
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }

    return bean;
}

创建代理

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   
	//已处理过
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
   
        return bean;
    //无需代理
    } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
   
        return bean;
    //非基础设施类且不被设置跳过
    } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
   
    	//获取增强方法
        Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
        if (specificInterceptors != DO_NOT_PROXY) {
   
        
        	//需要代理
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            
            //创建代理
            Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            
            //放入缓存
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        } else {
     //未获得增强方法
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    } else {
    //基础设施类或被设置跳过
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
}

代码逻辑并不复杂,首先看下获取增强方法:

获取增强方法

AbstractAdvisorAutoProxyCreator

@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
   
    List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
    return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   

	//获取所有增强
    List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
    
    //获取适用增强
    List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

	//扩展
    this.extendAdvisors(eligibleAdvisors);

	//排序
    if (!eligibleAdvisors.isEmpty()) {
   
        eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
    }

    return eligibleAdvisors;
}

AnnotationAwareAspectJAutoProxyCreator

protected List<Advisor> findCandidateAdvisors() {
   	
	//XML配置
    List<Advisor> advisors = super.findCandidateAdvisors();
	//注解配置
    if (this.aspectJAdvisorsBuilder != null) {
   
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }

    return advisors;
}

这里只关心通过注解进行的配置:

public List<Advisor> buildAspectJAdvisors() {
   
    List<String> aspectNames = this.aspectBeanNames;

	//第一次,无缓存
    if (aspectNames == null) {
   
        synchronized(this) {
   
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
   
                List<Advisor> advisors = new ArrayList();
                List<String> aspectNames = new ArrayList();
				
				//获取所有bean
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
                String[] var18 = beanNames;
                int var19 = beanNames.length;

                for(int var7 = 0; var7 < var19; ++var7) {
   
                    String beanName = var18[var7];
                    if (this.isEligibleBean(beanName)) {
   
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        //bean是否注解@Aspect
                        if (beanType != null && this.advisorFactory.isAspect(beanType)) {
   
                            aspectNames.add(beanName);
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值