SpringAOP笔记整理

        我们都知道,想使用SpringAop需要做一些xml配置,其中很大一部分是基于标签的,这些标签并不是Spring原生,而是自定义注解。Spring中如果声明了自定义注解,那么就一定会在程序中的某个地方注册了对应的解析器。我们的分析也是由此开始。

        我们全局搜索后发现了AopNamespaceHandler类,点进去看下:

public class AopNamespaceHandler extends NamespaceHandlerSupport {

	/**
	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
	 * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
	 * and '{@code scoped-proxy}' tags.
	 */
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}

        其中,可以看到在init方法中对应“aspectj-autoproxy”的是AspectJAutoProxyBeanDefinitionParser这个类。继续跟进这个类看看new出这个类是干什么的。结果在其中找到了parse方法

@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		extendBeanDefinition(element, parserContext);
		return null;
	}

因为所有解析器,因为是对BeanDefinitionParse接口的统一实现,入口都是从parse函数开始的。其中有用的代码是registerAspectJAnnotationAutoProxyCreatorIfNecessary,这是关键代码逻辑实现

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {

		//1.注册或者升级AnnotationAwareAspectJAutoProxyCreator
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		//2.处理proxy-target-class以及expose-proxy属性
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    //3.注册组件并通知,便于监听器做进一步处理
		//其中beanDifinition的className为AnnotationAwareAspectJAutoProxyCreator
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

这段代码就完成了所有需要做的事,3个步骤完成了三件事,。我们接下一个步骤一个步骤分析

一:动态AOP自定义标签

1:注册或者升级AnnotationAwareAspectJAutoProxyCreator

对于 AOP 的实现,基本上都是靠 AnnotationAwareAspectJAutoProxyCreator 去完成,它可以根据@Point 注解定义的切点来自动代理相匹配的 bean。但是为了配置简便, Spring 使用了自定义配置来帮助我们自动注册AnnotationAwareAspectJAutoProxyCreator,其注册过程就是在这里实现的 。

    @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(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());
				}
			}
			//已存在自动代理创建器且和现在的一致,就返回null用原有的
			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;
	}

如果已经存在了自动代理创建器就需要根据优先级判断具体使用那个,如果不存在那么就需要创建。我们可以看到,这段代码本质上是对AnnotationAwareAspectJAutoProxyCreator类的封装与创建,具体这个类干了什么我么稍后会加以分析。现在让我们继续看看这三步中的第二步干了什么

2.处理proxy-target-class以及expose-proxy属性

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
		if (sourceElement != null) {
			boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
			//对于proxy-target-class属性的处理
			if (proxyTargetClass) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			//对于expose-proxy属性的处理
			boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
			if (exposeProxy) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

1.proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。首先说明下proxy-target-class="true"和proxy-target-class="false"的区别,为true则是基于类的代理将起作用(需要cglib库,强制使用CGLIB代理),为false或者省略这个属性,则标准的JDK 基于接口的代理将起作用。关于这两个代理的区别

JDK 动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理 。
CGLIB 代理:实现原理类似于 IDK 动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类 。 CGLIB 是高效的代码生成包,底层是依靠 ASM (开源的 Java字节码编辑类库)操作字节码实现的,性能比 JDK 强 。

2.expose-proxy

简而言之,这个参数就是实现方法内部调用拦截的。

3.注册组件并通知

private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
		if (beanDefinition != null) {
			BeanComponentDefinition componentDefinition =
					new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
			parserContext.registerComponent(componentDefinition);
		}
	}

二:创建AOP代理

之前说过,通过Spring的自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator类型的自动注册,那么这个类到底用来干什么呢?我们继续分析。先来看一下这个类的继承关系结构图:

可以看到,最上层这个类是实现了BeanPostProcessor接口。而一旦实现这个接口,当Spring加载这个Bean时会在实例化前调用其postProcessAfterInitialization方法的。代理的本质是生成一个新的类,所以这个被加载的Bean就是被代理的Bean。

我们想分析AOP臭婆娘个这个方法着手,但发现AnnotationAwareAspectJAutoProxyCreator并没有这个方法,于是向上逐层查找,最后在其父类AbstractAutoProxyCreator找到了该方法:

@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			//根据给定的bean的class和name构建出一个key,格式:beanClassName_beanName
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				//如果它适合被代理,则需要封装指定bean
				return 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;
		}
		//无须增强
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		//给定的bean类是否代表一个基础设施类(在这里指是否是Aop基础类),
		// 基础设施类不应代理,或者配置了指定bean不需要自动代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		//如果存在增强方法则创建代理
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			//创建代理对象
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

前半部分几乎都是一些判断。真正创建代理的代码是从getAdxicesAndAdvisorsForBean开始的。

之后主要包含了两个步骤:

1.获取增强方法或者增强器

2.根据获取的增强进行代理

我们先看看增强方法:

@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//获取所有的增强
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//寻找所有增强中适用于bean的增强并应用
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

第一段代码是查找可用增强并返回,第二段代码是其内部实现。我们当然不满足于就此打住,继续跟进。

其内部实现又分成了两个步骤一是获取所有的增强二是寻找所有增强中适用于bean的增强并应用。由代码可见findCandidate与findAdvisorsThatCanApply便是做了这两件事。

我们继续跟踪AnnotationAwareAspectJAutoProxyCreator的findCandidate

@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		//这里调用父类的方法加载配置文件中的AOP声明
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.optimization
		//上一步保留了父类对AOP的XML配置文件的支持,这一步也添加了获取Bean的注解增强的功能。
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

super.findCandidateAdvisors是保留了父类的获取配置文件中定义的增强,this.aspectJAdvisorsBuilder.buildAspectJAdvisors是添加了Bean的注解增强的功能。步骤:

1.获取所有的beanName,这一步骤中所有在beanFactory中注册的bean都会被提取出来。

2.遍历所有的beanName,并找出声明AspenctJ注解的类,进行进一步的处理

3.对标记为AspectJ注解的类进行增强器的提取

4.将提取结果加入缓存

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

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new LinkedList<>();
					aspectNames = new LinkedList<>();
					//获取所有的beanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						//不合法的bean则略过,由子类定义规则,默认返回true
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						//获取对应的bean类型
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						//如果存在Aspect注解
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								//解析标记AspectJ注解中的增强方法
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								} else {
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							} else {
								// Per target or per this.
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								MetadataAwareAspectInstanceFactory factory =
										new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
								this.aspectFactoryCache.put(beanName, factory);
								advisors.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;
					return advisors;
				}
			}
		}

		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		//记录在缓存中
		List<Advisor> advisors = new LinkedList<>();
		for (String aspectName : aspectNames) {
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
			if (cachedAdvisors != null) {
				advisors.addAll(cachedAdvisors);
			} else {
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		return advisors;
	}

其中getAdvisors方法时增强器的获取


	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

		//标记为AspectJ的类
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		//获取标记为AspectJ的name
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		//验证
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new LinkedList<>();
		for (Method method : getAdvisorMethods(aspectClass)) {
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		//如果寻找的增强器不为空而且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

到这里增强器就获取完了(更详细的增强器获取不再做讨论,可见书P187),回顾一下创建代理的两个步骤:

1.获取增强方法或者增强器

2.根据获取的增强器进行代理

让我们回到创建代理的第二步,也就是wrapIfNecessary中的createProxy方法上来:

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

		//决定对于给定的bean是否应该使用targetClass而不是它的接口代理
		//检查proxyTargetClass设置以及preserveTargetClass属性
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		//将拦截器封装为增强器
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		//加入增强器
		proxyFactory.addAdvisors(advisors);
		//设置要代理的类
		proxyFactory.setTargetSource(targetSource);
		//定制代理
		customizeProxyFactory(proxyFactory);

		//用来控制代理工厂被配置后,是否还允许修改通知
		//缺省值为false(即在代理被配置之后,不允许修改代理的配置)
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

对于代理类及的创建和处理,Spring委托给了ProxyFactory去处理,而次函数中主要是对ProxyFactory的初始化操作,进而对真正的创建代理做准备,初始化步骤:

1.获取当前类中的属性

2.添加代理接口

3.封装Advisor并加入到ProxyFactory中

4.设置要代理的类

5.在Spring中还为子类提供了定制函数customizeProxyFactory,子类可以在此函数中进行对ProxyFactory的进一步封装

6.进行获取代理操作

未完待续……

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值