<aop:aspectj-autoproxy/>
在开启AOP时,bean.xml一定会开启这个标签,而Spring启动的时候,就需要将这个标签以及标签的解析器注册到Spring 容器中。
// 注册 <aspectj-autoproxy/> 标签及其解析器
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
AspectJAutoProxyBeanDefinitionParser 类是标签 <aop:aspectj-autoproxy /> 的解析器,该类实现了 BeanDefinitionParser 接口,并实现了 BeanDefinitionParser#parse 接口方法,属于标准的标签解析器定义。Spring 容器在启动时会调用 AspectJAutoProxyBeanDefinitionParser#parse 方法解析标签,实现如下:
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 注册标签解析器,默认使用 AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 解析 <aop:include /> 子标签,记录到 BeanDefinition 到 includePatterns 属性中
this.extendBeanDefinition(element, parserContext);
return null;
}
该方法做了两件事情:注册标签解析器和处理 <aop:include /> 子标签。
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
// 1. 注册或更新代理创建器 ProxyCreator 的 BeanDefinition 对象
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 2. 获取并处理标签的 proxy-target-class 和 expose-proxy 属性
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 3. 注册组件,并发布事件通知
registerComponentIfNecessary(beanDefinition, parserContext);
}
根据标签解析器创建ProxyCreator 代理创建器的BeanDefinition对象:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
传入一个AOP的代理创建器的class对象,BeanDefinition注册器和标签
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果名为 org.springframework.aop.config.internalAutoProxyCreator 的 bean 已经在册
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 已经在册的 ProxyCreator 与当前期望的类型不一致,则依据优先级进行选择
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
// 选择优先级高的 ProxyCreator 更新注册
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 没有对应在册的 ProxyCreator,注册一个新的
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;
}
这里简述一下所述代码的逻辑:
- 期望注册一个ProxyCreator的BeanDefinition,这个代理创建器的默认实现类是AnnotationAwareAspectJAutoProxyCreator,如果有存在了,就不创建,直接选择优先级最高的那个
- 如果不存在这个代理创建器,就创建一个并注册到Registry里面。
创建完代理创建器后,就要解析标签了
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); 这一行代码
主要是解析aop:aspectj-autoproxy/ 的 proxy-target-class 和 expose-proxy 属性配置,这两个操作都是给之前那个ProxyCreator添加一些属性,后面才用到
- proxy-target-class 是判断用jdk动态代理还是CGLIB代理
-
- false 表示使用 java 原生动态代理
-
- true 表示使用 CGLib 动态
- expose-proxy 代表要不要对内部方法实现增强
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
/*
* 获取并处理 proxy-target-class 属性:
* - false 表示使用 java 原生动态代理
* - true 表示使用 CGLib 动态
*
* 但是对于一些没有接口实现的类来说,即使设置为 false 也会使用 CGlib 进行代理
*/
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
// 为之前注册的 ProxyCreator 添加一个名为 proxyTargetClass 的属性,值为 true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
/*
* 获取并处理 expose-proxy 标签,实现对于内部方法调用的 AOP 增强
*/
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
// 为之前注册的 ProxyCreator 添加一个名为 exposeProxy 的属性,值为 true
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
ProxyCreator好像很重要,决定了什么代理,怎么增强,他其实是是实现了BeanPostProcessor 后置处理器,然后它实现了postProcessAfterInitialization方法
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
然后下一个是具体的实现
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 如果 beanName 不为空则直接使用 beanName(FactoryBean 则使用 &{beanName}),否则使用 bean 的 className
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 尝试对 bean 进行增强,创建返回增强后的代理对象
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
该方法的核心在于调用 AbstractAutoProxyCreator#wrapIfNecessary 方法尝试基于 AOP 配置对当前 bean 进行增强,并返回增强后的代理对象。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 已经处理过,直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 不需要进行增强的 bean 实例,直接跳过
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 对于 AOP 的基础支撑类,或者指定不需要被代理的类,设置为不进行代理
if (this.isInfrastructureClass(bean.getClass()) || this.shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获取适用于当前 bean 的 Advisor
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 基于获取到的 Advisor 为当前 bean 创建代理对象
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
简述一下上面的流程:如果在增强的时候这个bean已经增强过或者不需要增强(this.advisedBeans.get(cacheKey) == false),则直接返回.
否则就选择合适的增强器进行增强,然后返回一个代理对象。
选择合适的增强器过程如下:
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取适用于当前 bean 的 Advisor
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
// 没有合格的 Advisor,不进行代理
if (advisors.isEmpty()) {
return DO_NOT_PROXY; // null
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取所有候选的 Advisor(包括注解的、XML 中配置的)
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
// 从所有 Advisor 中寻找适用于当前 bean 的 Advisor
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 如果 Advisor 不为空,则在最前面追加一个 ExposeInvocationInterceptor
this.extendAdvisors(eligibleAdvisors);
// 对 Advisor 进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
简述一下上面的流程:先获取程序中的所有增强器,如果有,找到所有匹配当前bean的增强器,如果找到了,就将这些增强器排序。(是按照 before 之类来排序吗)
protected List<Advisor> findCandidateAdvisors() {
// 调用父类的 findCandidateAdvisors 方法,兼容父类查找 Advisor 的规则
List<Advisor> advisors = super.findCandidateAdvisors();
// 获取所有注解定义的 Advisor
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
方法首先调用了父类的实现,这主要是为了兼容父类查找候选增强器的规则,例如我们的示例中使用的是注解方式定义的增强,但是父类却是基于 XML 配置的方式查找增强器,这里的兼容能够让我们在以注解方式编程时兼容其它以 XML 配置的方式定义的增强。
具体的获取增强器的流程:
- 获取容器中所有的beanName 集合
- 过滤出切面(@Aspect、以ajc$ 开头的字段等)
- 每一个切面的切点生成对应的增强器并缓存,避免重复
具体看一下如何获取切点以生成增强器:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取切面 aspect 对应的 class 和 beanName
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 校验切面定义的合法性
this.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 ArrayList<>();
// 1. 遍历处理切面中除被 @Pointcut 注解以外的方法
for (Method method : this.getAdvisorMethods(aspectClass)) {
Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 2. 如果增强器不为空,同时又配置了增强延迟初始化,则需要追加实例化增强器 SyntheticInstantiationAdvisor
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 3. 获取所有引介增强定义
for (Field field : aspectClass.getDeclaredFields()) {
// 创建引介增强器 DeclareParentsAdvisor
Advisor advisor = this.getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
描述上述方法的过程:
- 获取切面的class和beanName’
- 校验
- 遍历@Around、@Before、@After、@AfterReturning,以及 @AfterThrowing 注解的方法
- 调用 getAdvisor 方法生成增强器
具体的getAdisor方法如下:
public Advisor getAdvisor(Method candidateAdviceMethod,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect,
String aspectName) {
// 校验切面类定义的合法性
this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 获取注解配置的切点信息,封装成 AspectJExpressionPointcut 对象
AspectJExpressionPointcut expressionPointcut = this.getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 依据切点信息生成对应的增强器
return new InstantiationModelAwarePointcutAdvisorImpl(
expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
描述getAdvisor方法如下:
- 校验(切面类的class对象)
- 获取注解配置的切点信息,封装成 Pointcut 对象
-
把PointCut、方法等属性封装成一个切点增强器对象 --》 InstantiationModelAwarePointcutAdvisorImpl()对象
这个切点增强器对象调用了一个增强器实例化方法,也就生成增强(先生成增强器,再生成增强):
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(
this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
public Advice getAdvice(Method candidateAdviceMethod,
AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder,
String aspectName) {
// 获取切面 class 对象,并校验切面定义
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
this.validate(candidateAspectClass);
// 获取方法的切点注解定义
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!this.isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]");
}
AbstractAspectJAdvice springAdvice;
// 依据切点注解类型使用对应的增强类进行封装
switch (aspectJAnnotation.getAnnotationType()) {
// @Pointcut
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
// @Around
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// @Before
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// @After
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// @AfterReturning
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
// @AfterThrowing
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);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
生成增强方法的过程主要为:
- 校验class
- 获取切点方法上的注解
- 对于每个注解,依据注解类型(@PointCut除外)进行增强类的封装。
- @AfterReturning 和 @AfterThrowing 特殊一点,因为他们还需要接收一个返回结果或者异常结果()
@AfterReturning(value = "execution(* com.springaop.aop01.Service.Impl.IUserServceImpl.*(..))",returning = "result")
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
@AfterThrowing(value = "execution(* com.springaop.aop01.Service.Impl.IUserServceImpl.*(..))",throwing = "exception")
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
在真正调用的时候:会触发一个invoke方法
public Object invoke(MethodInvocation mi) throws Throwable {
// 执行增强方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 执行目标方法
return mi.proceed();
}
先调用增强方法,再调用目标方法
以上是普通的增强方法的调用,接下来是引介增强方法
使用专门的 DeclareParentsAdvisor 类创建对应的增强器
private Advisor getDeclareParentsAdvisor(Field introductionField) {
// 获取 @DeclareParents 注解定义
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
return null;
}
// 没有指定默认的接口实现类
if (DeclareParents.class == declareParents.defaultImpl()) {
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
}
// 使用 DeclareParentsAdvisor 类型创建对应的引介增强器
return new DeclareParentsAdvisor(
introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
找到bean中的所有增强器后,需要为当前的bean匹配合适的增强器findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
// 没有候选的增强器,直接返回
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 1. 筛选引介增强器
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
// 表示是否含有引介增强
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 2. 筛选其它类型的增强器
for (Advisor candidate : candidateAdvisors) {
// 引介增强已经处理过,这里直接跳过
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 筛选其它类型的增强器
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
方法首先会使用类过滤器(ClassFilter)筛选引介增强器,然后,方法会过滤筛选其它类型的增强器,如果没有任何一个增强器适用于当前 bean 类型,则方法最终会返回值为 null 的 DO_NOT_PROXY 数组对象,表示当前 bean 不需要被增强。这里增强器已经筛选完毕了,那么就要创建增强代理对象了
Object proxy = this.createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
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 用于为目标 bean 实例创建代理对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// proxy-target-class = false,表示使用 JDK 原生动态代理
if (!proxyFactory.isProxyTargetClass()) {
// 检测当前 bean 是否应该基于类而非接口生成代理对象,即包含 preserveTargetClass=true 属性
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
// 如果是基于接口生成代理,则添加需要代理的接口到 ProxyFactory 中(除内置 callback 接口、语言内在接口,以及标记接口)
else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 将拦截器封装成 Advisor 对象
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 模板方法,定制代理工厂
this.customizeProxyFactory(proxyFactory);
// 设置代理工厂被配置之后是否还允许修改,默认为 false,表示不允许修改
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 基于 ProxyFactory 创建代理类
return proxyFactory.getProxy(this.getProxyClassLoader());
}
具体流程如下:
- 新建一个代理工厂ProxyFactory,
- 判断是否要用jdk来代理还是CGLib来代理
- 将拦截器封装成Advisor对象
- 创建代理对象
拦截器封装成代理对象如下:
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 已经是 Advisor,则无需多做处理
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 要求必须是 Advice 类型
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
// 如果是 MethodInterceptor,则直接使用 DefaultPointcutAdvisor 进行包装
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
// 否则遍历注册的适配器,如果存在关联的适配器则使用 DefaultPointcutAdvisor 进行包装
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
重点分析一下通过代理工厂 ProxyFactory 创建增强代理对象的过程
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy() // 1. 创建 AOP 代理
.getProxy(classLoader); // 2. 基于 AOP 代理创建目标类的增强代理对象
}
该方法的执行过程可以拆分成两个步骤:
- 创建 AOP 代理,Spring 默认提供了两种 AOP 代理实现,即 java 原生代理和 CGLib 代理;
- 基于 AOP 代理创建目标类的增强代理对象。
如果目标类实现了接口,则 Spring 默认会使用 java 原生代理。
如果目标类未实现接口,则 Spring 会使用 CGLib 生成代理。
如果目标类实现了接口,但是在配置时指定了 proxy-target-class=true,则使用 CGLib 生成代理。
创建完代理后,就要增强代理对象
首先来看一下jdk代理对象的增强。Java 原生代理要求代理类实现 InvocationHandler 接口,并在 InvocationHandler#invoke 方法中实现代理增强逻辑。
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 {
// 当前是 equals 方法,但是被代理类接口中未定义 equals 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return this.equals(args[0]);
}
// 当前是 hashCode 方法,但是被代理类接口中未定义 hashCode 方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return this.hashCode();
}
// 如果是 DecoratingProxy 中定义的方法(即 DecoratingProxy#getDecoratedClass),直接返回目标类对象
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
} else if (!this.advised.opaque // 允许被转换成 Advised 类型
&& method.getDeclaringClass().isInterface() // 接口类型
&& method.getDeclaringClass().isAssignableFrom(Advised.class)) // 方法所在类是 Advised 类及其父类
{
// 直接反射调用该方法
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 结果值
Object retVal;
// 指定内部间调用也需要代理
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取当前方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
// 拦截器链为空,则直接反射调用增强方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
// 否则需要创建对应的 MethodInvocation,以链式调用拦截器方法和增强方法
else {
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())) {
// 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);
}
}
}
流程描述:
-
特殊处理 Object#equals、Object#hashCode、DecoratingProxy#getDecoratedClass,以及
Advised 类及其父类中定义的方法; -
如果配置了 expose-proxy 属性,则记录当前代理对象,以备在内部间调用时实施增强;
-
获取当前方法的拦截器链;
-
如果没有拦截器定义,则直接反射调用增强方法,否则先逐一执行拦截器方法,最后再应用增强方法;
-
处理返回值。
重点来看一下步骤 4 中应用拦截器方法的实现
public Object proceed() throws Throwable {
// 如果所有的增强都执行完成,则执行增强方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
}
// 获取下一个需要执行的拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 动态拦截器,执行动态方法匹配
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 动态匹配成功,执行对应的拦截方法
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
// 动态匹配失败,忽略当前拦截器方法,继续执行下一个拦截器
else {
return this.proceed();
}
}
// 静态拦截器,直接应用拦截方法
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}