(二)Spring AOP源码-2.从@EnableAspectJAutoProxy开始说起

我们知道,Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:<aop:aspectj-autoproxy/>,或者使用@EnableAspectJAutoProxy注解。现在流行使用注解,那我们就以@EnableAspectJAutoProxy这个注解为源头来学习Spring AOP的源码。

从@EnableAspectJAutoProxy开始看起

先来看一下注解的源码:

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

	/**
	 * true——使用CGLIB基于类创建代理;false——使用JDK动态代理基于接口创建代理
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 是否通过aop框架暴露该代理对象
	 */
	boolean exposeProxy() default false;
}

我们发现它import了一个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) {

	//注册AnnotationAwareAspectJAutoProxyCreator		
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		//对于proxyTargetClass以及exposeProxy属性为true的处理
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
}

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);这行代码的详细实现

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
	return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
	// 这里容器中注册了一个AnnotationAwareAspectJAutoProxyCreator的bean。
	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

代码看到这里,可以知道AnnotationAwareAspectJAutoProxyCreator是个非常重要的class。

注册AnnotationAwareAspectJAutoProxyCreator

接着上面的代码,继续看,就是AnnotationAwareAspectJAutoProxyCreator的注册或升级过程。

	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) {
					//改变bean最重要的就是改变bean所对应的className属性  
					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;
	}
处理proxyTargetClass和exposeProxy

@EnableAspectJAutoProxy注解的源码中有两个方法:

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

	/**
	 * true——使用CGLIB基于类创建代理;false——使用JDK动态代理基于接口创建代理
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 是否通过aop框架暴露该代理对象
	 */
	boolean exposeProxy() default false;
}

在对这两个属性做了处理,如果proxyTargetClass属性为true,则强制使用CGLIB代理。如果exposeProxy为true,则暴露当前代理对象为ThreadLocal模式。

if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
	AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
	AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}

强制使用的过程,也是设置BeanDefinition属性的过程

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

public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
	}
}

以上就是AnnotationAwareAspectJAutoProxyCreator的注册过程。注册完后,是做了什么工作来实现AOP的操作呢?且听下回分解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值