一、SpringAop 代理创建 以及 执行过程
在上篇文章中分析得出在使用 Aop
时,实际向 Spring
容器中注入了一个 AnnotationAwareAspectJAutoProxyCreator
动态代理 bean
生成处理器,该类有实现 BeanPostProcessor
扩展方法,并且在 postProcessAfterInitialization
进行了代理的创建,主要逻辑在 AbstractAutoProxyCreator
类下的 wrapIfNecessary
方法中,上篇文章主要分析的该方法下getAdvicesAndAdvisorsForBean
方法,主要做了对切面方法的扫描和匹配过程,并且这里拿到的结果就是所有匹配的切面方法包装类集合,本篇文章继续上篇文章的脚步,分析下后面代理对象的创建过程和执行过程。
下面是上篇文章的地址:
SpringAop 源码解析 (一) - Aspect 切面方法的查找匹配过程
二、动态代理类型的判断过程
上面文章分析到这个位置,下面继续,如果存在匹配的切面方法,则先进行标记,反之不存在也进行标记,下次再进来该 beanName
时,不存在就直接跳过了。
这里看到获取到匹配的切面方法后,通过 createProxy
方法创建了代理对象,下面看到该方法下:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
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());
}
这里创建了一个代理工厂,并将切面方法、目标 bean
资源等,设置进入了该代理工厂中。
下面主要看到 proxyFactory.getProxy
又是如何创建代理对象的:
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
这里首先使用 createAopProxy
方法创建一个 AopProxy
,然后再通过AopProxy
的 getProxy
生成代理对象。
这里先看到 createAopProxy
方法下,在 ProxyCreatorSupport
类中:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 通过 aop动态代理工厂 创建 aop动态代理
return getAopProxyFactory().createAopProxy(this);
}
这里通过 AopProxyFactory
中 createAopProxy
创建一个 AopProxy
,默认情况下 AopProxyFactory
的具体实现为 DefaultAopProxyFactory
类,在ProxyCreatorSupport
类的无参构造方法中进行初始化的。
下面看到 DefaultAopProxyFactory
类中的 createAopProxy
方法中:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!IN_NATIVE_IMAGE &&
(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.");
}
// 如果被代理对象是接口,则使用jdk动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 如果被代理对象没有实现接口,则使用 cglib 动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 当前环境是否是原生环境,原生环境,使用 jdk动态代理
return new JdkDynamicAopProxy(config);
}
}
这里判断目标类是否有实现接口,如果有的话则使用 JDK
的动态代理,否则的话使用 cglib
进行代理。
下面回到上面的 getProxy
方法中,createAopProxy()
方法生成的要么是JDK
的动态代理,要么是 cglib
的动态代理,这里首先看下 JDK
动态代理的创建过程。
三、JDK 动态代理创建过程
这里先分析下 JdkDynamicAopProxy
类
可以看到实现了 InvocationHandler
接口,因此在执行代理时,会触发该类下的 invoke
方法。
再看下 JdkDynamicAopProxy
类的构造方法中做了什么事情:
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
//判断增强器和拦截器的数量
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
//如果为0就抛出异常
throw new AopConfigException("No advisors and no TargetSource specified");
}
//注入配置
this.advised = config;
// 获取完整的代理接口,并进行缓存
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 判断有没有定义的equals方法和hashCode方法
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
这里先判断增强器也就是切面方法是否存在,如果不存在代理也没有意义了,接着将配置注入到 advised
属性中,最后标记出被代理类是否有定义 equals
方法和 hashCode
方法。
下面再看到 getProxy
方法,如何生成代理对象的:
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 通过JDK 的 Proxy完成动态代理
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
直接通过 Proxy.newProxyInstance
创建代理实例,并且 InvocationHandler
就是自己,也就是触发执行代理时会触发该类下的 invoke
方法。
四、JDK 动态代理执行过程
JDK
动态代理执行,直接看到动态的代理的 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 {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
// 如果被代理对象没有重写 equals方法,则调用本地的方法。 比较的是被代理对象
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
// 如果被代理对象没有重写 hashCode 方法,则调用本地的 hashCode 方法。
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
// 如果实现了 DecoratingProxy的方法,则 分发给代理配置
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...
// 使用代理配置在ProxyConfig上调用服务
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 实际方法的返回值
Object retVal;
// 如果需要暴露至 threadLocal,则进行暴露
// 目的是在同一个类中自我方法调用的情况下
// 由于执行问题 被调用的无法执行代理
// 因此可以通过配置 exposeProxy 为 true,将代理方法缓存到 threadLocal 中
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);
// Get the interception chain for this method.
// 获取被代理类的当前方法的增强器链
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);
}
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();
}
// Massage return value if necessary.
// 对方法结果进行处理
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;
}
//如果返回值为null,并且返回类型不是void类型,并且返回类型还被定义为基本数据类型
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);
}
//如果暴露过proxyContext
if (setProxyContext) {
// Restore old proxy.
// 恢复为原始的proxy
AopContext.setCurrentProxy(oldProxy);
}
}
}
这里讲下 this.advised.exposeProxy
的作用,该值就是使用 @EnableAspectJAutoProxy
注解中的 exposeProxy
参数,如果是 true
的话,则会对当前代理对象进行缓存,目的是在同一个类中自我方法调用的情况下,如果被调用的方法带有 @Transactional
或 @Async
等注解,直接调用方法注解会失效,因为指向的是this
指针,并不是代理类,因此可以设置 exposeProxy
参数为true,将代理类缓存下来,自我调用时使用 AopContext.currentProxy()
获取到当前的代理对象,例如下面的案例:
@Component
public class TestAop {
public void test(){
System.out.println("test...");
// 自我调用
((TestAop) AopContext.currentProxy()).test2();
}
@Transactional
public void test2(){
System.out.println("test2");
}
}
这里的缓存其实就是使用的 ThreadLocal
进行的存储:
在继续看 invoke
方法,下面使用 this.advised.getInterceptorsAndDynamicInterceptionAdvice
生成所有匹配的切面方法的执行链,下面看到该方法中:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
这里会对执行链进行缓存,这里看下缓存中不存在时,调用的 this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
方法:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
// 通知器适配注册表
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 从动态代理配置中,获取 通知器列表
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
// 遍历通知器
for (Advisor advisor : advisors) {
// 切点通知器
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
// 切点通知器,需要对切面条件进行条件匹配验证
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
// 当切点匹配时,再根据切点的配置情况,加入拦截器列表
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
// 当切面匹配器已经在工作时,则放入 InterceptorAndDynamicMethodMatcher,运行时匹配
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 拦截器通知器
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
在该方法中,获取到之前匹配出来的切面方法,再次进行筛选匹配。
下面再回到 invoke
方法中,接着向下看如果执行链为空则直接使用 AopUtils.invokeJoinpointUsingReflection
方法触发目标方法,逻辑如下:
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
如果执行链存在,则根据切面的配置,构造一个 ReflectiveMethodInvocation
切面方法的执行链,执行链中包含了切面方法、目标方法、目标对象等:
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
// 拦截器的动态方法匹配器
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
再向下看则调用了 invocation.proceed()
,其实是触发所有的切面增强方法,最后再触发目标方法,看到 ReflectiveMethodInvocation
类中,逻辑如下:
public Object proceed() throws Throwable {
// 该方法为 jdk的AOP实现的核心
// 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);
}
//如果动态匹配失败,递归进行proceed
//不匹配就不执行当前的拦截器
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);
}
}
这里使用 currentInterceptorIndex
变量表示当前触发的第几个切面增强方法,首先判断的当 currentInterceptorIndex
等于interceptorsAndDynamicMethodMatchers
最后一个时,就是代表所有的切面方法都触发完了,这里的 invokeJoinpoint()
等一会再看。
先来看
((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)
是如何触发的目标切面方法,这里可以看到实现有很多种:
这里还是以 MethodBeforeAdviceInterceptor
为例,表示 @Before
前置通知方法:
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 继续触发下一个
return mi.proceed();
}
这里通过 this.advice.before
触发前置通知方法后,又递归的方式触发下一个切面增强方法。这里看下 this.advice.before
怎么触发的前置通知方法:
最终触发的是 invokeAdviceMethodWithGivenArgs
方法,逻辑如下:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
//对参数处理
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
//下面就是通过反射来调用方法了
//先让方法变得可以访问
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
//使用切面实例共产获取切面实例,然后执行建言方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
通过反射直接触发目标切面方法。
下面再回到 proceed()
方法中,当执行完所有的切面方法后会触发 invokeJoinpoint
方法:
这里和前面无执行链时调用逻辑一样,使用AopUtils.invokeJoinpointUsingReflection
方法触发目标方法。
五、cglib 动态代理创建过程
cglib
动态代理和 JDK
动态代理实现逻辑大致相同,这里还是先看下继承关系:
继承了 CglibAopProxy
,主要代理创建的逻辑其实都在 CglibAopProxy
中,构造方法也是调用了父类的构造方法中:
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
同样也是将配置注入到 advised
属性中,下面主要看到 getProxy
方法 中:
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// 获取需要被代理的对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
// 如果已经被代理过,则获取原始对象
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
// 将原始类需要被实现的接口进行重写
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
// 对类进行合法性验证
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// 创建 Enhancer 实例对象
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 设置需要被代理的类
enhancer.setSuperclass(proxySuperClass);
// 设置需要被代理的接口
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
// 设置回调拦截器
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// 创建cglib动态代理实例
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
这里主要声明了 cglib
中的 Enhancer
实例,并填充代理的信息,其中创建代理对象在 createProxyClassAndInstance
方法中:
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
六、cglib 动态代理执行过程
在 JDK
动态代理时,触发代理类时会触发 invoke
方法,同样在 cglib
代理中,触发代理类时,会触发 Enhancer
中 callbacks
类中的 intercept
方法,下面就从 callbacks
开始分析:
在前一步创建代理时 callbacks
就是通过 getCallbacks
方法获取的结果,下面看到该方法下:
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
//判断是不是要进行曝光
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
// 创建 cgLib 层面的动态切面拦截器,动态代理通过它完成
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
//判断是否要曝光
//根据是否要曝光并且是动态代理还是静态代理去生成拦截器
//这里的targetInterceptor拦截器称为目标拦截器
//这个拦截器的作用实质上没有对方法进行增强,但里面的额外操作会将当前代理对象切面曝光出来
//Cglib还支持静态代理咧。。。
if (exposeProxy) {
//如果要曝光,对应要创建exposedInterceptor
//并且从创建方法可以看到,直接给了目标对象,并没有给增强器
//在这里exposedInterceptor是会对代理对象进行曝光的
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
//如果不需要曝光,创建unadvvisedInterceptor,从名字就可以看出,是一个没有增强器的拦截器
//但其实还会对返回值做一些处理
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
// 创建targetDispatcher,这个跟unadvisedInterceptor的作用其实差不多
// 直接执行目标对象的方法,本质上没有做其他任何其他增强操作,不过可能会对返回值做一些处理
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
// 将切面包装成拦截器链
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.、
//如果目标对象是静态的或者拦截器链是冻结的
//这里会做一些修复措施
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
//遍历目标对象类型的所有方法
for (int x = 0; x < methods.length; x++) {
//当前的方法
Method method = methods[x];
//获取目标当前的方法需要执行的拦截器链,每个方法要进行的拦截器链都不一样
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
//封装成FixedChainStaticTargetInterceptor存放进fixedCallBacks中
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
//将三个callBacks都集合起来
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
这里对切面增强方法生成了一个 DynamicAdvisedInterceptor
下面主要看下 DynamicAdvisedInterceptor
中的 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 {
// 如果需要暴露至 threadLocal,则进行暴露
// 目的是在同一个类中自我方法调用的情况下
// 由于执行问题 被调用的无法执行代理
// 因此可以通过配置 exposeProxy 为 true,将代理方法缓存到 threadLocal 中
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);
}
}
}
可以看到这里实现逻辑和JDK
代理时的大致相同,如果 exposeProxy
为true
,就缓存暴露至threadLocal
中,同样使用 this.advised.getInterceptorsAndDynamicInterceptionAdvice
生成切面增强方法链。
最后 proceed()
方法同样是触发的父类的方法,和 JDK
代理执行了相同的 proceed()
方法:
public Object proceed() throws Throwable {
try {
return super.proceed();
}
catch (RuntimeException ex) {
throw ex;
}
catch (Exception ex) {
if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) {
throw ex;
}
else {
throw new UndeclaredThrowableException(ex);
}
}
}