本篇文章介绍下SpringAOP的用法以及源码分析。
我们定义四个类
package com.woods.aop;
/**
* 业务类,一个数学计算器
*/
public class MathCalculator {
public int divide(int x, int y) {
return x / y;
}
}
package com.woods.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
/**
* 切面
*/
@Aspect
public class LogAspect {
/**
* 抽取公共的切点表达式
*/
@Pointcut("execution(public int com.woods.aop.MathCalculator.*(..))")
public void pointCut() {
}
/**
* public int com.woods.aop.MathCalculator.div(int, int)是切入点表达式,指定在哪个方法进行切入
* public int com.woods.aop.MathCalculator.*(..)表示MathCalculator的任意参数的任意方法的
*/
// @Before("public int com.woods.aop.MathCalculator.div(int, int)")
@Before("com.woods.aop.LogAspect.pointCut()")
public void logStart(JoinPoint joinPoint) {
String parameterNameWithValue = getParameterNameWithValue(joinPoint);
System.out.printf("logStart, parameterNameWithValue:[%s]\n", parameterNameWithValue);
}
@After("pointCut()")
public void logEnd() {
System.out.println("logEnd");
}
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturn(JoinPoint joinPoint, Object result) {
System.out.printf("logReturn, method:[%s], result:[%d]", joinPoint.getSignature().getName(), result);
}
/**
* JoinPoint必须出现在参数列表的第一位
*/
@AfterThrowing(value = "pointCut()", throwing = "exception")
public void logException(JoinPoint joinPoint, Exception exception) {
System.out.printf("logException, method:[%s], exception:[%s]", joinPoint.getSignature().getName(), exception);
}
@Around(value = "pointCut()")
public Object logAround(ProceedingJoinPoint proceedingJoinPoint) {
System.out.printf("logAround, before method:[%s] execute\n", proceedingJoinPoint.getSignature().getName());
try {
return proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
System.out.printf("logAround, in exception, method:[%s] execute\n",
proceedingJoinPoint.getSignature().getName());
return null;
}
}
private String getParameterNameWithValue(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
String methodName = methodSignature.getMethod().getName();
Object[] args = joinPoint.getArgs();
String[] parameterNames = methodSignature.getParameterNames();
StringBuilder builder = new StringBuilder(args.length + 1);
builder.append("MethodName:").append(methodName).append(" Parameters: ");
for (int i = 0; i < parameterNames.length; i++) {
String parameterName = parameterNames[i];
String parameterValue = args[i].toString();
builder.append(parameterName)
.append(":")
.append(parameterValue)
.append(" ");
}
return builder.toString();
}
}
package com.woods.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.woods.aop.LogAspect;
import com.woods.aop.MathCalculator;
/**
* 配置类
*/
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAop {
@Bean
public MathCalculator mathCalculator() {
return new MathCalculator();
}
@Bean
public LogAspect logAspect() {
return new LogAspect();
}
}
package com.woods.test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.woods.aop.MathCalculator;
import com.woods.config.MainConfigOfAop;
/**
* 测试类
*/
public class IocAopTest {
@Test
public void testAop() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAop.class);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
// CglibAopProxy的intercept方法执行
mathCalculator.divide(2, 1);
logger.info("mathCalculator doneeeee ");
// 注意不能自己new MathCalculator().divide(1, 2),这不是Spring托管的实例,因此不会走切面
}
}
首先需要明确的是AOP(Aspect-oriented Programming,面向切面编程)不是Spring提出的概念,而是一种编程的理念,与OOP类似。
总体来讲,AOP做的事情就是在我们某些类中的某些方法执行前后,插入一些公共的逻辑。例如我们想在类A的方法methodA和和类B的方法methodB执行前插入一些公共的逻辑,例如打印一下审计日志,那么就可以定义一个切面,作用于类A和类B,从而实现公共的逻辑,避免重复编码。
AOP涉及到一些常见的概念,这里我们结合上面的示例来简单介绍下。
总体来讲,通过使用@EnableAspectJAutoProxy注解,向容器中添加了一个AnnotationAwareAspectJAutoProxyCreator。AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,因此在创建需要被切面切入的单实例Bean时(示例中的MathCalculator),AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization会为目标对象创建一个基于CGLIB或JDK动态代理的代理对象,我们之后通过getBean方法从Spring容器中获取MathCalculator时,拿到的就是代理对象了,调用divide方法时也是调用的代理对象被增强过的方法。
大体流程如下。
通过在配置类上增加@EnableAspectJAutoProxy注解开启了SpringAOP的功能,即为切面作用的类生成代理对象,这个代理对象可以通过CGLIB或JDK动态代理来生成
在@EnableAspectJAutoProxy注解中,通过@Import(AspectJAutoProxyRegistrar.class)引入了AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar向BeanFactory中注册了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition。这个步骤在refresh方法中的invokeBeanFactoryPostProcessors中完成。对invokeBeanFactoryPostProcessors方法的解析,详见invokeBeanFactoryPostProcessors
IoC容器初始时,在AbstractApplicationContext的refresh方法中的registerBeanPostProcessors方法中,会将BeanDefinition转化成Bean实例,从而拦截后续单实例Bean的创建
AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,在实例化目标对象时(被切面切入的类的实例,例如示例中的MathCalculator实例),Spring调用AnnotationAwareAspectJAutoProxyCreator的
postProcessAfterInitialization为目标对象生成了代理对象
后续从容器中getBean时,获取的就是代理对象了。在调用代理对象的方法时,Spring会把通知封装成拦截器,在方法调用前后就行拦截,从而实现Spring的功能。
在测试类中,我们通过applicationContext.getBean(MathCalculator.class)获取了一个MathCalculator的实例,注意这个时候获取的实例已经是一个Spring为我们生成的代理对象了,因此在调用mathCalculator.divide(2, 1)方法时,Spring可以拦截方法的执行。那么问题来了,Spring是通过何种方式为我们生成代理对象的呢?这要从@EnableAspectJAutoProxy注解说起。
首先看下@EnableAspectJAutoProxy注解的定义,该注解中的proxyTargetClass如果只为true,则使用CGLIB动态代理,否则Spring会在CGLIB动态代理和JDK动态代理中二选一。
package org.springframework.context.annotation;
/**
* Enables support for handling components marked with AspectJ's {@code @Aspect} annotation,
* similar to functionality found in Spring's {@code } XML element.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see org.aspectj.lang.annotation.Aspect
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
@EnableAspectJAutoProxy中标注了@Import注解,说明要向Spring容器中导入配置类,我们知道@Import中可以是Class、ImportSelector接口实现类、ImportBeanDefinitionRegistrar接口的实现类。可以看到这里Import的是AspectJAutoProxyRegistrar.class,它实现了ImportBeanDefinitionRegistrar接口,我们接着看下这个类。
AspectJAutoProxyRegistrar的作用是向BeanFactory中注册了一个AnnotationAwareAspectJAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,我们为目标类生成代理对象就是由AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法完成的。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
看到这里终于出现AnnotationAwareAspectJAutoProxyCreator类了,SpringAOP产生的代理对象就是由该类生成的。
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
下面是将AnnotationAwareAspectJAutoProxyCreator转化成BeanDefinition,注册到BeanFactory中的代码。
@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());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
那么问题来了,Spring容器是在什么时候执行的AspectJAutoProxyRegistrar的registerBeanDefinitions方法的呢?
想知道这个很简单,我们在下面这行打上断点即可。
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
可以看到,在初始化AnnotationConfigApplicationContext时,执行到了AbstractApplicationContext的refresh方法中的invokeBeanFactoryPostProcessors方法。对invokeBeanFactoryPostProcessors方法的解析,我们已经在invokeBeanFactoryPostProcessors这篇文章中讲过了。这里针对SpringIoC容器是如何处理的@Import中的ImportBeanDefinitionRegistrar再介绍一下。
invokeBeanFactoryPostProcessors执行时,最终调用的是ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法,该方法完成了对配置类的扫描,在上面的示例代码中配置类是mainConfigOfAop。
ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法对ImportBeanDefinitionRegistrar的处理过程如下所示。
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(configClasses),将配置类封装在configClasses集合中,BeanDefinitionReader将configClasses转化成BeanDefinition
ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()),从configClass中拿到所有实现ImportBeanDefinitionRegistrar接口的集合,
调用ImportBeanDefinitionRegistrar接口集合中的每个实现类的registerBeanDefinitions方法,从而最终调用到了AspectJAutoProxyRegistrar的registerBeanDefinitions,完成了AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor转化成BeanDefinition的过程。
到目前为止,我们已经知道了AnnotationAwareAspectJAutoProxyCreator这个为目标对象生成代理对象的类是如何转化成BeanDefinition的了,下一步就看一下这个BeanDefinition是在何时变成一个Bean的。
在SpringIoC容器的创建中我们讲过,在初始化AnnotationConfigApplicationContext的过程中,AbstractApplicationContext的registerBeanPostProcessors方法将BeanPostProcessor对应的BeanDefinition实例化成了Bean。
AnnotationAwareAspectJAutoProxyCreator实现了Ordered接口,因此是在registerBeanPostProcessors方法中下面的代码中,通过beanFactory.getBean(ppName, BeanPostProcessor.class)完成了将BeanDefinition转化成Bean的过程。
AnnotationAwareAspectJAutoProxyCreator对应的BeanName是"org.springframework.aop.config.internalAutoProxyCreator"。
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
beanFactory.getBean的具体流程我们在初始化单实例Bean中讲过。大致的流程是,首先从DefaultListableBeanFactory的单例池singletonObjects中取,如果拿不到,则新创建一个。在创建时,首先会创建一个AnnotationAwareAspectJAutoProxyCreator的实例,然后进行属性填充已经执行生命周期回调方法。经过以上步骤,Spring就把AnnotationAwareAspectJAutoProxyCreator的BeanDefinition转化成了Bean。在创建MathCalculator实例时,会调用AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization方法,生成代理对象。
到目前为止,我们已经有了AspectJAwareAdvisorAutoProxyCreator这个Bean,并且它是一个BeanPostProcessor,它的父类AbstractAutoProxyCreator重写了postProcessAfterInitialization方法,在这个方法中Spring为我们创建了MathCalculator的代理对象。
我们在AbstractAutoProxyCreator的postProcessAfterInitialization打上断点,可以看到在初始化AnnotationConfigApplicationContext时,在AbstractApplicationContext的finishBeanFactoryInitialization方法中(我们在初始化单实例Bean中详细介绍过该方法),在执行Bean的生命周期回调,即应用BeanPostProcessor的postProcessAfterInitialization时,调用了AbstractAutoProxyCreator的postProcessAfterInitialization,为MathCalculator生成了代理对象。
AbstractAutoProxyCreator的postProcessAfterInitialization方法,为目标对象MathCalculator创建了代理对象。我们看下该方法的源码。
该方法传入bean就是还没被代理的MathCalculator对象,返回的是通过CGLIB或JDK动态代理生成的代理对象。
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@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;
}
在wrapIfNecessary方法中,比较重要的两行代码是getAdvicesAndAdvisorsForBean以及createProxy。
getAdvicesAndAdvisorsForBean方法主要是获取所有的通知方法,createProxy则是为目标对象创建代理对象的方法。下面分别来看下。
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
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;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 获取当前bean的所有增强器(通知方法)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 将当前的beanName保存到advisedBeans中
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象,Spring自动决定用jdk动态代理还是cglib动态代理
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;
}
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();
}
/**
* Find all eligible Advisors for auto-proxying this class.
* @param beanClass the clazz to find advisors for
* @param beanName the name of the currently proxied bean
* @return the empty List, not {@code null},
* if there are no pointcuts or interceptors
* @see #findCandidateAdvisors
* @see #sortAdvisors
* @see #extendAdvisors
*/
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;
}
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
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);
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);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
@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);
}
}
经过前面的步骤,Spring已经为我们的MathCalculator对象创建出了基于CGLIB的代理对象,我们从ApplicationContext中getBean(MathCalculator.class)时,拿到的就是这个代理对象。
接下来,我们执行mathCalculator的divide方法,执行该方法时,会进入到CglibAopProxy中的intercept方法。
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
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);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 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 = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
在List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);这行代码中,通知方法被封装成了拦截器链,
紧接着retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();这行代码将proxy等参数封装成了一个CglibMethodInvocation对象,通过调用这个对象的proceed方法完成了整个方法的调用,我们看下proceed方法。
interceptorsAndDynamicMethodMatchers就是我们的通知方法,
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return 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 {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
SpringFramework系列目录