您的位置:首页 > 编程语言 > Java开发

Spring基于注解形式的 AOP的原理流程及源码解析(一)

2017-11-06 10:02 871 查看
在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);

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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring 源码 aop 注解