Spring基於註解形式的 AOP的原理流程及原始碼解析(一)
阿新 • • 發佈:2019-01-09
在Spring的配置類上添加註解@EnableAspectJAutoProxy:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class MvcContextConfig extends WebMvcConfigurerAdapter {
}
Spring在解析此類時,會解析類上的所有註解,如果這個註解是一個合成註解,合成的註解元素中含有Spring內有特殊作用的註解,則會遞迴的解析。
@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;
}
EnableAspectJAutoProxy 的元註解中含有@Import註解,此註解在Spring容器中負責引入一個類,此類若是一個普通的類,則當做一個Bean,和@ComponentScan掃描註解生成的Bean一樣;若是一個ImportSelecter,則從幾個類中篩選出一個類,返回其全名,到時候生成此Bean;若引入的是一個ImportBeanDefinitionRegistrar的實現類,則能夠手動根據註解的資訊註冊BeanDefinition,到時候生成Bean。
@EnableAspectJAutoProxy 的元註解中含有@Import,引入了一個ImportBeanDefinitionRegistrar的實現類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);
//註冊一個AOP代理實現的Bean
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
AspectJAutoProxyRegistrar 根據註解@EnableAspectJAutoProxy上的屬性來註冊相應的Bean,proxyTargetClass = true 指定使用CGLIB來作為AOP的代理實現方式。若不設定此屬性,則預設使用jdk proxy作為代理實現方式。他們兩者的區別是: jdk動態代理只支援介面的方法代理,不支援類自身的方法,它動態地生成一個代理類,繼承自Proxy,實現被代理的介面,內部持有被代理物件;而CGLIB則支援所有的方法代理,它動態生成一個代理類,繼承自被代理類,所以叫TargetClass。
public abstract class AopConfigUtils {
//有三種AOP的配置形式,有基於Spring內建的,有基於使用者配置檔案的,有基於註解的,基於註解的優先順序最高,
//一般配置一種就可以,如果配置多種則優先順序高的會覆蓋優先順序低的
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
//註冊AnnotationAwareAspectJAutoProxyCreator到容器中,此類負責基於註解的AOP動態代理實現
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
//設定支援類的代理,設定此屬性到時候會使用CGLIB來生成動態代理類
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
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;
}
}