Spring Aop 图解

1.切面术语

  • Aspect【切面】:横切多个类的关注点的模块化。事务管理是企业Java应用程序中横切关注点的一个很好的例子。在Spring AOP中,切面是通过使用标准类(基于schema的风格)或使用@Aspect注解标注的标准类(@AspectJ风格)来实现的。
  • Join point【连接点】:Spring并没有抽象自己的连接点,而是复用AspectJ第三方包的JointPoint。切面规范并不是由Spring提出的,它只是一个包装者(基于AspectJ这个第三方包进行包装)。标准的定义中,JointPoint【连接点】是应用程序执行过程中的一个候选点,可以在该候选点插入切面。该候选点可以是方法调用时、异常抛出时,甚至可以是属性字段被修改时。我们可以在这些JointPoint【连接点】将切面的代码插入到应用程序的正常流程中,以提供新的行为。But:Spring只提供了狭义的JointPoint【连接点】,即Spring仅仅支持方法调用时这唯一的JointPoint【连接点】类型!!
  • Advice【增强/通知/建言】:这个词的中文表述很多,我们不纠结于用哪个表述。Advice表示的是切面【Aspect】在特定连接点【Join Point】上采取的操作。Advice有多种类型:@Before、@After、@Around。许多AOP框架(包括Spring)将Advice建模为拦截器,在连接点【Join Point】周围维护了一个拦截器链【chain of interceptors 】。(具体而言,@Aspect声明了一个切面,它只是一个标准的Java类,而在程序执行到了连接点【Join Pont】时,我们需要将切面插入其中,这就要求切面需要有行为,Advice即为切面的行为。为了更细致的控制切面,Spring提供了多种类型的Advice,并在底层以拦截器的模式实现它们,这样在进入连接点【Join Point】时,就链式拦截,以调用适当的Advice进行增强 )
  • Pointcut【切入点】:它是一个匹配连接点【Join Point】的谓词(谓词就是一个条件表达式)。Advice与切入点【Pointcut】表达式相息息相关,并在切入点【Pointcut】匹配的任何连接点【JoinPoint】上运行。Spring仅仅支持方法执行时连接点【Join Point】,因此Spring所支持的所有切入点表达式语法,都是为了匹配方法的执行而已~~
  • AOP proxy【AOP代理】:由AOP框架创建的一个对象,该对象满足/实现了切面的契约(如增强方法的执行,等等)。在Spring框架中,一个AOP代理可以是JDK动态代理或CGLIB代理。
  • Advisor【增强器】:Spring中特有的一个概念,它是Advice和Pointcut复合体。

2.准备

XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:contexts="http://www.springframework.org/schema/context"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <contexts:annotation-config />
    <!--注:component-scan隐式的开启了annotation-config,其实可以不写的-->
    <contexts:component-scan base-package="com.telecom.spring.inside"/>
    <context:property-placeholder location="classpath:config/bean.properties"/>
	 <!--注:开启aop自动代理-->
    <aop:aspectj-autoproxy>
        <!--指定待代理的Bean的命名规范,只有符合命名规范的才会被切面代理,include可以有多个,多个之间是或的关系-->
        <!--<aop:include name="" />-->
    </aop:aspectj-autoproxy>


</beans>

Java:

@Component
public class HealthService {
	/**
	* 待代理的方法
	*/
    public String echo(String message){
    	System.out.println(message)
        return message;
    }
}

Main:

    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("config/Bootstrap_${env}.xml");
        HealthService healthService = (HealthService) classPathXmlApplicationContext.getBean("healthService");
        healthService.echo("hello");
    }

3 aspectj-autoproxy

public class AopNamespaceHandler extends NamespaceHandlerSupport {

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

概述:假定您已经知道自定义元素的解析过程。
加载BeanDefinition时,当遇到< aop:aspectj-autoproxy />,DefaultNamespaceHandlerResolver会根据元素的命名空间URI,搜索出其对应的NamespaceHandler,即AopNamespaceHandler,然后根据元素类型,找到其对应的BeanDefinitionParser,即AspectJAutoProxyBeanDefinitionParser。调用其parse(Element element, ParserContext parserContext)方法,对给定的元素(即< aop:aspectj-autoproxy />元素)进行解析。

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		//1,0 如果需要的话,注册一个AspectJ的自动代理创建器:AnnotationAwareAspectJAutoProxyCreator
		// 注册到BenaDefinitionRegustry上哟!!
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		// 因为<aop: aspectj-autoproxy>允许有子节点,即<aop:include name="" />,
		// 用于约束切面仅对满足该命名规范的Bean生效,该方法的目的就是将所解析出的name,
		// 添加到BeanDefinition的includePattern属性上,这些name都是一些正则表达式,用于匹配Bean的名字
		extendBeanDefinition(element, parserContext);
		return null;
	}
}

重点显而易见,下面着重分析AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);

public abstract class AopNamespaceUtils {

	public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";

	private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
	public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
		//1.0 注册AspectJ的自动代理创建器:AnnotationAwareAspectJAutoProxyCreator
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		//2.0 分别处理<aop:aspectj-autoproxy>中的子元素:proxy-target-class和expose-proxy
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}
	private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
		if (sourceElement != null) {
			//提取proxy-target-class属性的值,并强制修改BeanDefinition的属性
			boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
			if (proxyTargetClass) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			//提取expose-proxy属性的值,并强制修改BeanDefinition的属性
			boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
			if (exposeProxy) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}
public abstract class AopConfigUtils {
	//强制修改BeanDefnition
	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);
		}
	}
}

AopNamespaceUtils的处理逻辑比较简单,先注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition到BeanDefinitionRegistry上,它是一个BeanPostProcessor,在Bean的init-method调用前后执行,完成对目标对象的代理,一会就会讲到。然后,因为< aop:aspectj-autoproxy />中还有两个配置元素:

  • proxy-target-class:默认为false,预示是否开启对CGLib的支持,默认false不开启,也就是以JDK动态代理来实现Aop
  • expose-proxy:目标对象内部的自我方法调用,将无法实施切面中的增强,即调取的是原生方法,并非代理后的方法,通过设置expose-proxy为true,我们可以使用语法糖实现目的,如下:
 public class SimplePojo implements Pojo {
	//foo 调用 bar,如果直接bar(),那么我们会发现,bar()方法并未被切面代理,而是直接调用的原生方法,这与Spring的Aop内存模型有关
    public void foo() {
        // this works, but... gah!
        ((Pojo) AopContext.currentProxy()).bar();
    }

    public void bar() {
        // some logic...
    }
}

接下来,我们来看到底是如何注册AnnotationAwareAspectJAutoProxyCreator的:

public abstract class AopConfigUtils {
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";
	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		// 调用其他方法
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}
	//注册或升级Aop相关的的BeanPostProcessor
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		//如果注册中心中存在BeanName = AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition
		// 那么需要判断谁的优先级更高一点,保留优先级最高的那一个
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			// 提取出BeanName = AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			// 如果Bean的类名是相同的,那么无需重复注册,如果类名不一致,则比较优先级,保留优先级最高的
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				// 已注册的优先级
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				// 本次待注册的优先级
				int requiredPriority = findPriorityForClass(cls);
				// 比较
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}
		// 如果注册中心不存在BeanName = AUTO_PROXY_CREATOR_BEAN_NAME的BeanDefinition
		// 那么创建一个,类名是传入的参数指定的,本例中则是AnnotationAwareAspectJAutoProxyCreator,并注册到BeanDefinitionRegistry上
		// 并将其类型角色设置为基础设施,优先级设置为最高
		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;
	}
}

4.Aop代理

前面,我们学习了注册AnnotationAwareAspectJAutoProxyCreator,它是SmartInstantiationAwareBeanPostProcessor的实现,而SmartInstantiationAwareBeanPostProcessor是InstantiationAwareBeanPostProcessor的子接口。

下面我们将所有相关的方法,笼聚到AnnotationAwareAspectJAutoProxyCreator方便查看:

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
	// 由自定义的TargetSource代理的Bean的缓存集合
	private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	// 循环引用时使用,用于暗示该beanName对应的Bean实例被循环引用了
	private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
	// 代理类型缓存,键为beanName的cacheKey,值为代理类的类型
	private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
	// 存储被增强的Bean的效果,键为beanName的cacheKey,值为bool值,表示该Bean是否需要被代理,
	// 如果为false,说明该Bean无需代理,true表示需要被代理
	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
	/**
	* 由InstantiationAwareBeanPostProcessor声明
	* 实例化之前调用,以决定是由Spring进行正常的实例化,还是直接被代理,如果被代理,则不需要Spring做正常
	* 的实例化以及自动装配。
	*/ 
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}
	/**
	* 由InstantiationAwareBeanPostProcessor声明
	* 在实例化之后,判定是否要对该Bean实例进行自动装配,默认都是true,即装配
	*/
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}
	/**
	* 由BeanPostProcessor声明
	* 在调用init-method方法前调用
	*/
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}
	/**
	* 由BeanPostProcessor声明
	* 在调用init-method方法后调用
	* 这里是AOP的代理核心
	*/	
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
	@Override
	@Nullable
	public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
		if (this.proxyTypes.isEmpty()) {
			return null;
		}
		Object cacheKey = getCacheKey(beanClass, beanName);
		return this.proxyTypes.get(cacheKey);
	}
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}
	//无用
	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
		return null;
	}
	//无用
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		return pvs;
	}
}

概述:我们用两个场景,将所有的AOP串起来

场景一:标准Aop代理(无自定义TargetSource)

在实例化Bean的步骤中,我们首先进入postProcessBeforeInstantiation方法,即在实例化Bean之前,给BeanPostProcessor一个机会,使得它可以代理目标对象,而不需要继续做标准的Bean实例化。

	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		//1.0 根据Bean的name和class,生成一个cacheKey,底层就是字符串的品专,用来标识唯一
		Object cacheKey = getCacheKey(beanClass, beanName);
		// 如果beanName不为空,或者beanName不为空且targetSourcedBeans这个缓存中不存在beanName对应的TargetSource记录,则进入if子句
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			// 如果advisedBeans中存在记录,则直接返回null,将Bean实例化的任务交给Spring去做
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			// 如果该类是一个基础设施类,或者该类是被skip跳过的,那么我们将其记录在advisedBeans,
			// 键为beanClass,值为false,并返回null,将Bean实例化的任务交给Spring去做
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// 如果存在自定义TargetSource,那么就需要在此创建代理对象,而不能将Bean实例化的任务交给Spring
		// 该代码可以抑制目标bean的不必要的缺省实例化:TargetSource将以自定义的方式处理目标实例。
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		// 如果确实存在自定义的TargetSource,那么将BeanName放到targetSourcedBeans中
		// 暗示这个BeanName的实例化由自定义的TargetSource来做,不由Spring处理
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			// 自定义代理的逻辑:
			// 1.获取所有的增强器Advisor
			// 2.使用自定义的targetSource,和增强器等,创建带来对象
			// 3.将代理后的对象的元数据,即class对象,存到proxyTypes中,以加速
			// 4.返回代理对象,并暗示Spring不要多管闲事!!
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			
			return proxy;
		}
	
		return null;
	}

在一个标准的场景中,我们没有定义自定义的TargetSource,故该方法返回null,继续进入Spring的实例化Bean的流程中。
接下来,我们看postProcessAfterInitialization,它是在init-method的调用后被执行的,此时Bean实例已经完全实例化,就可以进行动态代理了~~

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

所有Aop的核心工作都基本在此。
earlyProxyReferences这个缓存变量中存储的提前代理引用,用于解决Spring中Bean循环引用。只有在被循环引用时,earlyProxyReferences中才会有数据,举个栗子:
A 依赖 B ,B 又依赖 A

  1. Spring实例化A的Bean,并注册其ObjectFactory到singleFactories中
  2. 在填充A Bean时,需要实例化A,注意,自动填充是发生在init-method调用之前
  3. Spring实例化B的Bean,则侧其ObjectFactory到singleFactories中
  4. 在填充B Bean时,通过benfactory的getBean方法,查找A的实例,最终在singletonFactories中找到了之前注册的一个提前代理引用,然后调用其ObjectFactory.getObject(),而该方法的真实实现是getEarlyBeanReference方法实现的。
  5. B自动填充结束
  6. B初始化结束
  7. A自动填充结束
  8. A初始化结束

我们将关注点放在wrapIfNecessary(bean,beanName,cacheKey)上:

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 如果beanName为空,且targetSourcedBeans缓存中存在beanName对应的代理Bean,则直接返回,无需再代理
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// advisedBeans中保存的是Bean是否需要代理,如果返回False,那么明确表示不需要代理该Bean
		// 具体见上面postProcessBeforeInstantiation的介绍
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 如果该bean是一个基础设施类或者是可skip的,那么将该类这种不需代理的本质记录下来并直接返回当前bean
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 如果存在可应用的增强advice,那么久为其创建代理
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			// 如果存在增强器,那么先记录该bean需代理的本质,然后为其创建代理
			// 注意这里使用的targetSources是SingletonTargetSource,与自定义的TargetSource的情况不同
			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;
	}

概述:本方法属于Aop代理的骨架方法,拆分步骤讲解:

  1. 通过targetSourcedBeans,判断是否可以对该Bean应用代理,因为该缓存只存储自定义的TargetSource代理的beanName,如果在该缓存中命中了beanName,那么该Bean已经是自定义TargetSource代理过的Bean,无需再代理了
  2. 通过advisedBeans,判断是否可以忽略对该Bean的代理,advisedBeans缓存中存储的是beanName -> bool,其中bool表示是否需要代理,如果FALSE,那么明确暗示该Bean无需代理
  3. 判断bean所对应的Class是否是一个基础设施类,或者是一个可skip忽略的类,如果是,那么亦不需要代理
  4. 获取可应用于该Bean上的增强
  5. 如果增强存在,那么记录该Bean需代理的本质,并创建器代理
  6. 如果增强不存在,那么记录该Bean无需代理的本质。

下面讲如何获取可应用到该Bean的增强器:

	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		// 找到所有适合自动代理该类的Advisor。
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		// List转数组
		return advisors.toArray();
	}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取所有候选Advisor,直白点讲,就是笨应用中所有的增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 获取仅对本Bean可应用的Advisor
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, 
        beanClass, beanName);
    // 留给子类用的hook,可以注册额外的的Advisor,默认啥也不干
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 对需要代理的Advisor按照一定的规则进行排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

首先,获取所有候选Advisor:

	protected List<Advisor> findCandidateAdvisors() {
		//调用父类,以适配XML形式配置的切面进行操作,提取出所有候选的Advisor
		List<Advisor> advisors = super.findCandidateAdvisors();
		// 注解方式的切面操作,提取出所有候选Advisor
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

我们着重看注解方式的:

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

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					// 调用BeanFactory,获取所有BeanDefinition的beanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					// 循环
					for (String beanName : beanNames) {
						// beanName是否有效,还记得<aop:include name="">标签吗,name最终会放到includePatterns中,它们是一堆正则表达式,这里就是验证beanName是否匹配。
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// 提取beanName对应的Class实例,如果无法确定Class,那么也无法代理,直接中断结束
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						// 如果该Class是一个Aaspect注解所标注的,那么就可以对其进行解析,以提取增强器了
						if (this.advisorFactory.isAspect(beanType)) {
							// 将切面的name存到缓存aspectNames中
							aspectNames.add(beanName);
							// 为该切面类重新建模,以AspectMetadata来维护其元数据,像@Aspect(value="perthis(...)")中的value属性,就会解析并放到元数据中保存
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								// 如果切面的实例化模型是单例的,创建单例模式的工厂类BeanFactoryAspectInstanceFactory实例
								// AspectInstanceFactory是用于提供AspectJ切面的实例的接口,
								// 它存在的原因是为了与BeanFactory解耦
								// MetadataAwareAspectInstanceFactory是AspectInstanceFactory的子接口,
								// 额外添加一个新方法,即getAspectMetadata(),可以获得与@Aspect注解额类的AspectMetadata
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								// 获取所有的Advisor
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								// 如果Bean是单例的,那么而直接将此时解析出的Advisors缓存到advisorsCache中,否则,就将工厂缓存到aspectFactoryCache中,以备再用
								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.
								// 切面的实例化模型并非单例,而bean却是单例的,这是违规的!!
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								// 创建Prototype的切面工厂类
								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 ArrayList<>();
		for (String aspectName : aspectNames) {
			// 先从advisorsCache缓存中提取切面name对应的Advisor列表,如果不存在,那么
			// 可能切面并非SINGLETON的,因此aspectFactoryCache可能存在对应的工厂缓存,
			// 取出MetadataAwareAspectInstanceFactory工厂,调用该工厂的getAdvisors()获取增强器
			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;
	}
}

buildAspectJAdvisors方法主要是获取应用中所有的切面,并解析,缓存,概括描述:

  1. 首先获取BeeanFactory中注册的BeanDefinition所对应的beanName
  2. 循环beanaNames,首先根据< aop >注解中引入includePatterns来排除beanName不匹配的
  3. 保留beanName所对应的类以@Aaspect标注的,将其BeanName缓存到aspectNames中,然后根据@Aspect注解中的value元数据(即切面的实例化类型)进行条件处理,如果value是SINGLETON或者默认值,那么创建BeanFactoryAspectInstanceFactory单例代理工厂类,解析出Advisors列表,并缓存;如果value并非SINGLETON,那么创建MetadataAwareAspectInstanceFactory原型代理工厂类,解析出Advisors列表,兵缓存。
  4. 当buildAspectJAdvisors方法调用后,缓存中都有了记录,在此调用就不会再加工所有的类了。直接从advisorsCache或者aspectFactoryCache中提取出Advisors列表即可

PS:概括中对缓存的存储与提取,表达的很简单,最好看下源代码中的注释

接下来我们来看如果提取Advisors:

public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		// 获取切面类的Class
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		// 获取切面类的名称,即beanName
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		// 对方法传入的MetadataAwareAspectInstanceFactory,进行包装,使得其仅会被实例化一次
		// 直白一点,就是使用包装模式,将实例化变得惰性,且单例
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
		// 获取切面了中所有的可能是增强的方法,即除了@Pointcut注解的方法之外的所有方法
		//拿到这所有的方法后,在调用getAdvisor(),提取出真的是增强的方法,即以@Around/@After/@Before注释的方法
		for (Method method : getAdvisorMethods(aspectClass)) {
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// 如果该切面@Aaspect(value="")中的value属性的值不是空或者SINGLETON,那么暗示
		// 它是原型实例化模式。对于这种,我们需要在最开始处(索引为0处),添加一个SyntheticInstantiationAdvisor增强器
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		//查找引介增强的属性(会单独讲)
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}
	// 反射获取所有的Mthod,剔除掉以@Pointcut注解的方法
	private List<Method> getAdvisorMethods(Class<?> aspectClass) {
		final List<Method> methods = new ArrayList<>();
		ReflectionUtils.doWithMethods(aspectClass, method -> {
			// Exclude pointcuts
			if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
				methods.add(method);
			}
		});
		methods.sort(METHOD_COMPARATOR);
		return methods;
	}
}

该方法中基本完全解释了如何获取Advisor,我们概述一下:

  1. 提取切面类的Class和beanName
  2. 延迟MetadataAwareAspectInstanceFactory的实例化,即单例化
  3. 首先提取增强方法,提取出所有非@Pointcut注解的方法,再分别对这些候选的增强方法,应用转换,转换为Advisor,我们下面会详细讲转换,故这里就一笔带过。
  4. 因为MetadataAwareAspectInstanceFactory的单例话,我们在Advisors列表的索引0处,插入一个SyntheticInstantiationAdvisor
  5. 最后获得所有的引介增强,并将其Field转换为DeclareParentsAdvisor对象,引介增强后面会详细讲,这里也一笔带过

提前介绍一下Advisor,它是一个高级接口,表示一个增强器,他有多重实现,我们枚举常用的几个:

  • DeclareParentsAdvisor:引介增强
  • InstantiationModelAwarePointcutAdvisorImpl:它是AspectJPointcutAdvisor的实现,每一个切面增强方法,都会有一个InstantiationModelAwarePointcutAdvisorImpl实例对应
  • SyntheticInstantiationAdvisor:实例化切面的同步增强器,在非单例的切面的per-clause切入点触发。该增强器无副作用

然后是Advice,它指的是增强,增强器(Advisor)是增强(Advice)和切入点(Pointcut)的聚合:

  • AspectJAroundAdvice:环绕增强/通知
  • AspectJMethodBeforeAdvice:@Before增强
  • AspectJAfterAdvice:@After增强
  • AspectJAfterReturningAdvice:@AfterReturning增强
  • AspectJAfterThrowingAdvice:@AfterThrowing增强

是时候看如何从切面类中解析Advisor了:

	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
		// 提取切入点
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
		// 我们说过,Advisor是Adviuceh和pointcut的聚合,上面已经提取出了pointcut,Spring
		// 将提取Advice的任务,交给了InstantiationModelAwarePointcutAdvisorImpl的构造器去做,
		// 并将Advice和pointcut组合成一个Advisor,这里指的就是InstantiationModelAwarePointcutAdvisorImpl
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}
	//提取切入点
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		// 提取方法上的注解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
		// 声明一个AspectJExpressionPointcut,它表示的是一个表达式切入点,
		// 类比而言,就是@Around(value = "logging()")中value属性的字符串的值,他就是表达式,也即切入点
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
		// 设置其切入点的表达式
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}

上面方法中解析的是切面类中的增强方法,即以@Around/@Before/@Aafter/@AterReturing/@AfterThrowing注解标注的方法。Advisor是Advice和Pointcut的聚合,先提取出Pointcut,它本质上就是一个表达式。然后将提取Advice和聚合成Advisor的工作全权交给了InstantiationModelAwarePointcutAdvisorImpl的构造器来实现的,我们追踪一下,看他是如何构造Advice的:

final class InstantiationModelAwarePointcutAdvisorImpl
		implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
	// 从以@Aspect注解标注的给定的类中提取出Advisor的工厂接口类
	private final AspectJAdvisorFactory aspectJAdvisorFactory;
	
	public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		this.declaredPointcut = declaredPointcut;
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		this.methodName = aspectJAdviceMethod.getName();
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		this.aspectInstanceFactory = aspectInstanceFactory;
		this.declarationOrder = declarationOrder;
		this.aspectName = aspectName;

		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			// 如果@Aaspect(value="") value属性值是Per-xxx的,即以非单例模式实例化的切面
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
			// 使之动态:必须从预实例化【pre-instantiation】状态更改为后实例化【post-instantiation 】状态。
			// 如果它不是一个动态切入点,那么在第一次评估之后,Spring AOP基础设施可能会对它进行优化。
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// @Aaspect(value="") value属性值是SNGLETON的,即以单例模式实例化的切面
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}
	private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
		// 根据给定的增强方法,即Method,获得一个对应的Advisor
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}
}

InstantiationModelAwarePointcutAdvisorImpl中只是一个实例化与聚合的骨架,并针对切面的实例化模式,实行不同的逻辑。
我们以切面单例实例化模式来讲,它将Advice的工作委托给instantiateAdvice(pointcut)方法,而该方法有委托给AspectJAdvisorFactory对象来做的,基础实现只有一个,即ReflectiveAspectJAdvisorFactory,该工厂的作用即使通过发射,将增强的Method转换为一个Advice:

	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);
		// 获取方法上的切面注解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
		// 校验下方法所属的类是否以@Aaspect标注
		if (!isAspect(candidateAspectClass)) {
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Found AspectJ method: " + candidateAdviceMethod);
		}

		AbstractAspectJAdvice springAdvice;
		// 工厂模式,根据不同的注解类型,生成不同的Advice实例
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

		// 配置Advice
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

越深入,越简单,一个简单工厂实现罢了。

方法增强解析完了,我们来看引介增强~~

	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		...其他省略了...
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}
		...其他省略了...
	}
	private Advisor getDeclareParentsAdvisor(Field introductionField) {
		DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
		if (declareParents == null) {
			// Not an introduction field
			return null;
		}

		if (DeclareParents.class == declareParents.defaultImpl()) {
			throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
		}

		return new DeclareParentsAdvisor(
				introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
	}

引增强的转换很简单,因为引介只能发生在属性上,因此提取出所有的Field,然后循环。提取出属性上的注解,如果存在@DeclareParents注解,那么它确实是引介增强,那么实例化一个DeclareParentsAdvisor,作为该引介增强的Advisor实现。
具体的对象构造就不看了,举个引介增强使用的例子,大家就懂了:

##TODO
提取出应用中所有的Advisor,我们来看如何找到可应用于该Bean的Advisor:

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//上面讲的
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 接下来讲的
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

我们看到底如何做的:


	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
		// ProxyCreationContext向ThreadLocal变量中设置当前处理的beanName,并在finally字句中移除掉
		// 因为是ThreadLocal是线程级的,而创建过程不涉及多线程,没什么安全问题
		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

重点代码是:AopUtils.findAdvisorsThatCanApply,即从所有Advisors中找出适合应用到本Bean的Advisors

	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		// 合格的增强器列表
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		// 优先处理引介增强
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			// 如果该Advisor已经在上面引介增强中处理过,那么就continue下一条
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			// 处理方法增强以及同步增强(SyntheticInstantiationAdvisor)
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}
	//判定该Advisor是否对该Bean可应用
	public static boolean canApply(Advisor advisor, Class<?> targetClass) {
		return canApply(advisor, targetClass, false);
	}
	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}
	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if (introductionAwareMethodMatcher != null ?
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

一些列的正则匹配,最终确定是否可以将该Advisor应用到该Bean实例上。

可应用的Aadvisors已经全部提取出来了,现在就是最后一步了,创建代理:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
	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 proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);
		// 判断当前proxyFactory是否设置了proxy-target-class = true,如果true,那么etProxyTargetClass(true),
		// 这会强制Spring在创建代理时使用CGLib动态代理
		// 而如果未设置,则调用evaluateProxyInterfaces()方法,评估是否存在父接口
		// 存在,则将其设置仅proxyFactory,如果不存在,则依然使用CGLib
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		// 将给定的specificInterceptors,包装转换为Advisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}
	// 如果待代理的类有接口,那addInterface()将其设置进proxyFactory
	// 否则,依然setProxyTargetClass(true)设置使用CGLib代理
	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) {
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;
				break;
			}
		}
		if (hasReasonableProxyInterface) {
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		else {
			proxyFactory.setProxyTargetClass(true);
		}
	}
}

该方法主要的两行代码,分别是:

  • buildAdvisor
  • proxyFactory.getProxy

我们分别讲解,先是buildAdvisor(…)

	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// 缺省情况下没有公共拦截器,或者所公共Aadvisor的
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
			// 如果commonInterceptors的长度大于0,那么需要与传入的specificInterceptors进行merge
			if (commonInterceptors.length > 0) {
				// 如果设置为优先应用公共Advisor,则将commonInterceptors放到索引0处
				// 否则添加到尾部
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}

		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			// 对Advisor包装,原地修改
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

构建Advisor,首先获取所有公共的Advisor,默认是没有的。然后将传入的specificInterceptors与刚解析出的commonInterceptors进行merge。最后则是进行wrap,最终均转换为Advisor,下面给出包装逻辑,其实很简单:

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


	/**
	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
	 */
	public DefaultAdvisorAdapterRegistry() {
		//如果传入的Advice是MethodBeforeAdvice,那么可适配
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		//如果传入的Advice是AfterReturningAdvice,那么可适配
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		//如果传入的Advice是ThrowsAdvice,那么可适配
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}
	//包装,该方法结束后,传入的adviceObject都会被转成Advisor,否则报错
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		// 1.0 如果本来就是SAdvisor,则直接返回
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		// 2.0 如果到这里,确定它不是一个Advice,那么抛出异常
		//     spring要求进到这个方法时,要么是Advice,要么是Advisor
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		// 强制转换
		Advice advice = (Advice) adviceObject;
		// 如果该Advice是一个拦截器MethodInterceptor类型,那么用DefaultPointcutAdvisor封装它
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		// 如果Advice并不是一个MethodInterceptor,那么使用本类固定的三个适配器,判断是否可适配
		// 如果可适配,则用DefaultPointcutAdvisor包装它,否则抛出异常
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}
}

获取了所有Advisors,下面就是创建代理这最后临门一脚了:

public class ProxyCreatorSupport extends AdvisedSupport {

	private AopProxyFactory aopProxyFactory;
	/**
	 * Create a new ProxyCreatorSupport instance.
	 */
	public ProxyCreatorSupport() {
		this.aopProxyFactory = new DefaultAopProxyFactory();
	}

	/**
	 * Create a new ProxyCreatorSupport instance.
	 * @param aopProxyFactory the AopProxyFactory to use
	 */
	public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
		Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
		this.aopProxyFactory = aopProxyFactory;
	}
	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}
	public AopProxyFactory getAopProxyFactory() {
		return this.aopProxyFactory;
	}
	
}

构建AopProxy的实现是在DefaultAopProxyFactory中实现的:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
	/**
	* 根据配置,确定使用哪个实现,到底是JdkDynamicAopProxy还是ObjenesisCglibAopProxy作为AopProxy的实例
	*/
	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}
}

通过这if条件语句,我们可以总结出Spring选取AopProxy实现的逻辑:

  1. 如果optimize设置为true,那么使用CGLIb实现
  2. 如果proxy-target-class设置为true,亦选取CGLIb实现
  3. hasNoUserSuppliedProxyInterfaces判断是否存在代理接口,如果待代理的类并没有父接口,那么依然是CGLib

Finally,创建代理,AopProxy.getProxy,有点复杂,直接看invoke方法:


final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
			// 如果需要在目标对象内获取对代理对象的感知,那么需要设置CurrentProxy属性为代理对象
			// 这样我们可以通过AopContext.getCurrentProxy()获取到当前被代理的类的代理类。
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// 从传给AopProxy的TargetSource中取出目标对象,即原始的对象
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// 获取该方法的拦截器链,其实是Advisor转换的
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// 看看有没有什么增强。如果不没有,我们可以退回到对目标方法的直接反射调用,并避免创建方法调用【MethodInvocation】
			if (chain.isEmpty()) {
				// 如果没有拦截器链,那么直接调用切点方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 如果有拦截器链,构建一个方法调用抽象,并通过拦截器链进入到连接点【Pointcut】
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// 执行拦截器链
				retVal = invocation.proceed();
			}

			// 返回结果
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
}
场景二:自定义TargetSource

首先看一下TargetSource的定义:

public interface TargetClassAware {

	/**
	 * Return the target class behind the implementing object
	 * (typically a proxy configuration or an actual proxy).
	 * @return the target Class, or {@code null} if not known
	 */
	@Nullable
	Class<?> getTargetClass();

}

public interface TargetSource extends TargetClassAware {

	/**
	 * 返回目标类型的Class实例
	 * @return the type of targets returned by this {@link TargetSource}
	 */
	@Override
	@Nullable
	Class<?> getTargetClass();

	/**
	 * 如果是静态的,那么getTarget()返回的就是相同的对象,否则,返回的不一定是一样的对象
	 * <p>In that case, there will be no need to invoke {@link #releaseTarget(Object)},
	 * and the AOP framework can cache the return value of {@link #getTarget()}.
	 * @return {@code true} if the target is immutable
	 * @see #getTarget
	 */
	boolean isStatic();

	/**
	 * 返回一个目标实例。在AOP代理的目标方法被调用时,会从targetSource中提取出目标对象,即原始对象。
	 * @return the target object which contains the joinpoint,
	 * or {@code null} if there is no actual target instance
	 * @throws Exception if the target object can't be resolved
	 */
	@Nullable
	Object getTarget() throws Exception;

	/**
	 * 释放由getTarget()方法返回的目标对象。
	 * Spring在完目标bean之后会调用这个方法释放目标bean对象,对于一些需要池化的对象,这个方法是必须
	 * 要实现的,这个方法默认不进行任何处理
	 */
	void releaseTarget(Object target) throws Exception;
}

看一下Spring官方提供的几个实现:
首先看简单的SingletonTargetSource,他也是我们最常用到的TargetSource:

public class SingletonTargetSource implements TargetSource, Serializable {

	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 9031246629662423738L;


	/** 缓存目标对象 */
	private final Object target;
	/**
	 * 根据给定的目标对象,创建一个SingletonTargetSource
	 * @param target the target object
	 */
	public SingletonTargetSource(Object target) {
		Assert.notNull(target, "Target object must not be null");
		this.target = target;
	}


	@Override
	public Class<?> getTargetClass() {
		return this.target.getClass();
	}
	// 返回目对象
	@Override
	public Object getTarget() {
		return this.target;
	}

	@Override
	public void releaseTarget(Object target) {
		// nothing to do
	}
	// 静态的,因此多次调用getTarget()都返回同一个目标对象
	@Override
	public boolean isStatic() {
		return true;
	}
	@Override
	public boolean equals(Object other) {
		if (this == other) {
			return true;
		}
		if (!(other instanceof SingletonTargetSource)) {
			return false;
		}
		SingletonTargetSource otherTargetSource = (SingletonTargetSource) other;
		return this.target.equals(otherTargetSource.target);
	}

	/**
	 * SingletonTargetSource uses the hash code of the target object.
	 */
	@Override
	public int hashCode() {
		return this.target.hashCode();
	}

	@Override
	public String toString() {
		return "SingletonTargetSource for target object [" + ObjectUtils.identityToString(this.target) + "]";
	}

}

SingletonTargetSource是我们在Aop中最常用的TargetSource实现,它提供了对目标对象的缓存,亦即我们在同一个代理对象中,调用多次aop方法,那么都是在同一个目标对象(即原始对象)上操作。

接下来看一个比较特殊的TargetSource,它是CommonsPool2TargetSource,它实现了池化:

public class CommonsPool2TargetSource extends AbstractPoolingTargetSource implements PooledObjectFactory<Object> {

	private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;

	private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;

	private long maxWait = GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;

	private long timeBetweenEvictionRunsMillis = GenericObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;

	private long minEvictableIdleTimeMillis = GenericObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;

	private boolean blockWhenExhausted = GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;

	/**
	 * Apache Commons 包的ObjectPool.
	 */
	@Nullable
	private ObjectPool pool;


	/**
	 * 创建一个CommonsPoolTargetSource,使用默认配置
	 * 默认池的最大大小为8。
	 * @see #setMaxSize
	 * @see GenericObjectPoolConfig#setMaxTotal
	 */
	public CommonsPool2TargetSource() {
		setMaxSize(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL);
	}


	/**
	 * 设置池中允许的空闲对象的最大数量,默认8
	 * @see GenericObjectPool#setMaxIdle
	 */
	public void setMaxIdle(int maxIdle) {
		this.maxIdle = maxIdle;
	}

	/**
	 * 返回池中允许的空闲对象的最大数量。
	 */
	public int getMaxIdle() {
		return this.maxIdle;
	}

	/**
	 * 设置池中空闲对象的最小数量。默认是0
	 * @see GenericObjectPool#setMinIdle
	 */
	public void setMinIdle(int minIdle) {
		this.minIdle = minIdle;
	}

	/**
	 * 返回池中所允许的空闲对象的最小数量。
	 */
	public int getMinIdle() {
		return this.minIdle;
	}

	/**
	 * 设置从池中获取对象的最大等待时间,默认-1,即一直等待
	 * @see GenericObjectPool#setMaxWaitMillis
	 */
	public void setMaxWait(long maxWait) {
		this.maxWait = maxWait;
	}

	/**
	 * 返回从池中获取对象的最大等待时间。
	 */
	public long getMaxWait() {
		return this.maxWait;
	}

	/**
	 * Set the time between eviction runs that check idle objects whether they have been idle for too long or have become invalid.
	 * Default is -1, not performing any eviction.
	 * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
	 */
	public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
		this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
	}

	/**
	 * Return the time between eviction runs that check idle objects.
	 */
	public long getTimeBetweenEvictionRunsMillis() {
		return this.timeBetweenEvictionRunsMillis;
	}

	/**
	 * 设置空闲对象在被驱逐之前可以驻留在池中的最小时间。默认值为1800000(30分钟)。
	 * <p>请注意,需要执行清除操作才能使此设置生效。
	 * @see #setTimeBetweenEvictionRunsMillis
	 * @see GenericObjectPool#setMinEvictableIdleTimeMillis
	 */
	public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
		this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
	}

	/**
	 * 返回空闲对象可以驻留在池中的最小时间。
	 */
	public long getMinEvictableIdleTimeMillis() {
		return this.minEvictableIdleTimeMillis;
	}

	/**
	 * 设置当池耗尽时调用是否应该停止。
	 */
	public void setBlockWhenExhausted(boolean blockWhenExhausted) {
		this.blockWhenExhausted = blockWhenExhausted;
	}

	/**
	 * 当池耗尽时调用是否应该阻塞。
	 */
	public boolean isBlockWhenExhausted() {
		return this.blockWhenExhausted;
	}


	/**
	 * 创建并持有一个ObjectPool
	 * @see #createObjectPool()
	 */
	@Override
	protected final void createPool() {
		logger.debug("Creating Commons object pool");
		this.pool = createObjectPool();
	}

	/**
	 * 如果子类想要返回特定的对象池,则可以覆盖此属性。
	 * @return an empty Commons {@code ObjectPool}.
	 * @see GenericObjectPool
	 * @see #setMaxSize
	 */
	protected ObjectPool createObjectPool() {
		GenericObjectPoolConfig config = new GenericObjectPoolConfig();
		config.setMaxTotal(getMaxSize());
		config.setMaxIdle(getMaxIdle());
		config.setMinIdle(getMinIdle());
		config.setMaxWaitMillis(getMaxWait());
		config.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
		config.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
		config.setBlockWhenExhausted(isBlockWhenExhausted());
		return new GenericObjectPool(this, config);
	}


	/**
	 * 从ObjectPool中借调对象
	 */
	@Override
	public Object getTarget() throws Exception {
		Assert.state(this.pool != null, "No Commons ObjectPool available");
		return this.pool.borrowObject();
	}

	/**
	 * Returns the specified object to the underlying {@code ObjectPool}.
	 */
	@Override
	public void releaseTarget(Object target) throws Exception {
		if (this.pool != null) {
			this.pool.returnObject(target);
		}
	}

	@Override
	public int getActiveCount() throws UnsupportedOperationException {
		return (this.pool != null ? this.pool.getNumActive() : 0);
	}

	@Override
	public int getIdleCount() throws UnsupportedOperationException {
		return (this.pool != null ? this.pool.getNumIdle() : 0);
	}


	/**
	 * Closes the underlying {@code ObjectPool} when destroying this object.
	 */
	@Override
	public void destroy() throws Exception {
		if (this.pool != null) {
			logger.debug("Closing Commons ObjectPool");
			this.pool.close();
		}
	}


	//----------------------------------------------------------------------------
	// Implementation of org.apache.commons.pool2.PooledObjectFactory interface
	//----------------------------------------------------------------------------

	@Override
	public PooledObject<Object> makeObject() throws Exception {
		return new DefaultPooledObject<>(newPrototypeInstance());
	}
	@Override
	public void destroyObject(PooledObject<Object> p) throws Exception {
		destroyPrototypeInstance(p.getObject());
	}
	@Override
	public boolean validateObject(PooledObject<Object> p) {
		return true;
	}
	@Override
	public void activateObject(PooledObject<Object> p) throws Exception {
	}
	@Override
	public void passivateObject(PooledObject<Object> p) throws Exception {
	}

}

CommonsPool2TargetSource实现非常简单的,其将主要功能都委托给了ObjectPool进行,ApacheCommon包提供的实现。通俗的讲,就是AopProxy在getTarget()时,从ObjectPool借调一个对象,用完之后再归还。

那么自定义TargetSource实在什么时候生效呢呢?其实是在Bean实例化之前,调用InstantiationAwareBeanPostProcessor(BeanPostProcess的子接口)所声明的postProcessBeforeInstantiation()方法中做的,我们来看一下由< aop:aspectj-autoproxy> 引入的AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor,在postProcessBeforeInstantiation()到底是如何做的:


	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// 获取自定义TargetSource,并使用该TargetSource,生成代理
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

postProcessBeforeInstantiation()是在Bean真正实例化前,Spring给BeanPosProcesosr一个机会,让其决定是否可以对该Bean应用代理(自定义代理),如果该方法的返回值不为null,那么说明该Bean被代理了,也就不需要继续由Spring实例化了,只需要再依次为该代理的Bean应用postProcessAfterInitialization()即可。

自定义TargetSource与非自定义的TargetSource,在代理的处理逻辑上基本一致,先获取可以应用于该Bean的Advisors列表,然后根据Advisors、TargetSource、beanName、beanClass为目标Bean创建代理。

那么TargetSource的getTarget()还有releaseTarget()到底是什么时候调用的?我们来看AopProxy的JDK实现,即JdkDynamicAopProxy,在他的invoke方法中,有这样的一段骨架代码:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// 获取资源,这在池化的TargetSource中很重要
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}

			// 返回值
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// 调用releaseTarget释放资源
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

}

概述:在真正执行目标方法前,通过调用传入给AopProxy的TargetSource的getTarget()方法获取到目标对象(即原始对象),然后调用代理的目标方法,在finally中最终调用releaseTarget(…)释放目标资源,在池化场景中,即将对象归还给ObjectPool

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值