AOP系列(三)SpringBoot中 AOP實現原理

1、簡介

AOP在Spring中實現,自動歸入IOC容器的管理,利用註解和動態代理技術,實現切面功能。spring

2、源碼分析

AopAutoConfiguration

@Configuration
    //條件配置類,知足條件,就開啓AOP功能
    @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() {
        }
    }
    }
複製代碼
  • AopAutoConfiguration是SpringBoot爲AOP提供的自動裝配類緩存

  • SpringBoot自動開啓Aop代理機制,默認CglibAutoProxyConfiguration配置。若是須要基於接口的動態代理(JDK基於接口的動態代理) , 須要設置spring.aop.proxy-target-class屬性爲false。框架

EnableAspectJAutoProxy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

/**
 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
 * to standard Java interface-based proxies. The default is {@code false}.
 */
boolean proxyTargetClass() default false;

/**
 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
 * @since 4.3.1
 */
boolean exposeProxy() default false;

}
複製代碼

註解開啓代理機制,告訴Spring容器,支持註解式Aspect。ide

  • proxyTargetClass 指定是否使用CGLIB的方式建立實現接口的目標對象的代理。缺省值爲false,使用JDK方式建立接口對象的代理。源碼分析

  • exposeProxy標記代理對象是否應該被aop框架經過AopContext以ThreadLocal的形式暴露出去。當一個代理對象須要調用它本身的另一個代理方法時,這個屬性將很是有用。默認是是false,以免沒必要要的攔截。post

AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

/**
 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
 * {@code @Configuration} class.
 */
@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);
		}
	}
}
}
複製代碼

這個類註冊AspectJAnnotationAutoProxyCreator,而且enableAspectJAutoProxy獲取EnableAspectJAutoProxy的註解信息,默認強制開啓類代理。ui

AopConfigUtils

public abstract class AopConfigUtils {

.....

@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAutoProxyCreatorIfNecessary(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 {
       // 註冊AnnotationAwareAspectJAutoProxyCreator
        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;
    }
}

}
複製代碼

開始的時候AutoProxyCreator類不存在,RootBeanDefinition初始化AnnotationAwareAspectJAutoProxyCreator類,註冊類到IOC容器。this

AnnotationAwareAspectJAutoProxyCreator

繼承關係lua

AnnotationAwareAspectJAutoProxyCreator->AspectJAwareAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAutoProxyCreatorspa

Bean生命週期的後置處理

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware{

 ......

  public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            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);
        //獲取要織入到beanName目標對象的切入點的全部通知
        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;
    }
}
....
}
複製代碼

重點:建立代理類

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 (this.shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        } else {
            this.evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    this.customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    if (this.advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    return proxyFactory.getProxy(this.getProxyClassLoader());
}
複製代碼

DefaultAopProxyFactory

繼承關係

DefaultAopProxyFactory->AopProxyFactory

建立代理工廠

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
        return new JdkDynamicAopProxy(config);
    } else {
        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.");
        } else {
            return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
        }
    }
}

}
複製代碼

class接口走JDK代理,類走Cglib代理。

AopProxy

繼承關係

JdkDynamicAopProxy->AopProxy

ObjenesisCglibAopProxy->CglibAopProxy->AopProxy

得到代理對象

public interface AopProxy {
   Object getProxy();

   Object getProxy(@Nullable ClassLoader var1);
}


 public Object getProxy() {
    return this.getProxy(ClassUtils.getDefaultClassLoader());
}
複製代碼

3、總結

1.AopAutoConfiguration實現Aop的自動裝配,配置好依賴就能直接使用。

2.EnableAspectJAutoProxy註解,開啓AspectJ的代理功能。

3.AspectJAutoProxyRegistrar實現動態註冊AnnotationAwareAspectJAutoProxyCreator,歸入IOC容器管理。

4.AnnotationAwareAspectJAutoProxyCreator實現生命週期監聽,後置處理AspectJ切入的類,查找緩存全部的Advisors,建立代理類對象。

5.DefaultAopProxyFactory提供代理策略,接口走JDK代理,類走Cglib代理。SpringBoot默認走Cglib代理。

6.AopProxy建立代理類,代理類裏面會插入Advisor註解的方法中的代碼,並返回代理對象。

相關文章
相關標籤/搜索