接着上一篇中的内容!
3、创建代理
在获取了所有的bean对应的增强器之后,便可以进行代理的创建了
org.springframework.aop.framework.autoproxy包下的AbstractAutoProxyCreator类中的createProxy方法
1 protected Object createProxy(Class<?> beanClass, @Nullable String beanName, 2 @Nullable Object[] specificInterceptors, TargetSource targetSource) { 3 4 if (this.beanFactory instanceof ConfigurableListableBeanFactory) { 5 AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); 6 } 7 8 ProxyFactory proxyFactory = new ProxyFactory(); 9 // 获取当前类中的相关属性 10 proxyFactory.copyFrom(this); 11 12 // 决定对于给定的bean是否应该使用targetClass属性,而不是他的接口代理,检查proxyTargetClass设置以及preserveTargetClass属性 13 if (!proxyFactory.isProxyTargetClass()) { 14 if (shouldProxyTargetClass(beanClass, beanName)) { 15 proxyFactory.setProxyTargetClass(true); 16 } 17 else { 18 // 添加代理接口 19 evaluateProxyInterfaces(beanClass, proxyFactory); 20 } 21 } 22 23 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); 24 // 加入增强器 25 proxyFactory.addAdvisors(advisors); 26 // 设置要代理的类 27 proxyFactory.setTargetSource(targetSource); 28 // 定制代理 29 customizeProxyFactory(proxyFactory); 30 // 用来控制代理工厂被配置之后,是否还允许修改通知 31 // 缺省值为false(即在代理被设置之后,不允许修改代理的配置) 32 proxyFactory.setFrozen(this.freezeProxy); 33 if (advisorsPreFiltered()) { 34 proxyFactory.setPreFiltered(true); 35 } 36 37 return proxyFactory.getProxy(getProxyClassLoader()); 38 }
对于代理类的创建和处理,spring委托给ProxyFactory处理,而此函数中主要是对ProxyFactory的初始化操作,进而对真正的创建代理做准备,这些初始化操作如下:
(1)获取当前类中的属性
(2)添加代理接口
(3)封装advisor并加入到ProxyFactory中
(4)设置要代理的类
(5)当然spring中还为子类提供了定制的函数customizeProxyFactory,子类在此函数中对ProxyFactory进一步封装
(6)进行获取代理操作
其中封装advisor并加入到ProxyFactory中以及创建代理是两个相对繁琐的过程,可以通过ProxyFactory提供的addAdvisor方法直接将增强器置入代理创建工厂中,
但是将拦截器封装成增强器还是需要一定的逻辑的
org.springframework.aop.framework.autoproxy包下的AbstractAutoProxyCreator类
1 protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) { 2 // Handle prototypes correctly... 3 // 解析注册的所有的InterceptorName 4 Advisor[] commonInterceptors = resolveInterceptorNames(); 5 6 List<Object> allInterceptors = new ArrayList<>(); 7 if (specificInterceptors != null) { 8 // 加入拦截器 9 allInterceptors.addAll(Arrays.asList(specificInterceptors)); 10 if (commonInterceptors.length > 0) { 11 if (this.applyCommonInterceptorsFirst) { 12 allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); 13 } 14 else { 15 allInterceptors.addAll(Arrays.asList(commonInterceptors)); 16 } 17 } 18 } 19 if (logger.isDebugEnabled()) { 20 int nrOfCommonInterceptors = commonInterceptors.length; 21 int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0); 22 logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + 23 " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors"); 24 } 25 26 Advisor[] advisors = new Advisor[allInterceptors.size()]; 27 for (int i = 0; i < allInterceptors.size(); i++) { 28 // 拦截器进行封装转化为Advisor 29 advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); 30 } 31 return advisors; 32 }
wrap方法在org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry类中重写
1 @Override 2 public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { 3 // 如果要封装的对象本身就是Advisor类型的,无需做过多的处理 4 if (adviceObject instanceof Advisor) { 5 return (Advisor) adviceObject; 6 } 7 // 因为此封装方法只对Advisor和Advice两种类型有效,不是的话,就抛出异常 8 if (!(adviceObject instanceof Advice)) { 9 throw new UnknownAdviceTypeException(adviceObject); 10 } 11 Advice advice = (Advice) adviceObject; 12 if (advice instanceof MethodInterceptor) { 13 // So well-known it doesn't even need an adapter. 14 // 如果是MethodInterceptor类型,则使用DefaultPointcutAdvisor类封装 15 return new DefaultPointcutAdvisor(advice); 16 } 17 // 如果存在Advisor的适配器那么也同样需要进行封装 18 for (AdvisorAdapter adapter : this.adapters) { 19 // Check that it is supported. 20 if (adapter.supportsAdvice(advice)) { 21 return new DefaultPointcutAdvisor(advice); 22 } 23 } 24 throw new UnknownAdviceTypeException(advice); 25 }
由于spring中涉及过多的拦截器、增强器、增强方法等方式来对逻辑进行增强,所以非常有必要统一封装成Advisor来进行代理的创建,完成了增强的封装过程,那么解析的
最重要的一步就是代理的创建和获取了
(1)创建代理
1 // org.springframework.aop.framework.ProxyFactory类中的 2 public Object getProxy(@Nullable ClassLoader classLoader) { 3 return createAopProxy().getProxy(classLoader); 4 } 5 6 protected final synchronized AopProxy createAopProxy() { 7 if (!this.active) { 8 activate(); 9 } 10 // 创建代理 11 return getAopProxyFactory().createAopProxy(this); 12 } 13 // org.springframework.aop.framework.DefaultAopProxyFactory类对createAopProxy()方法进行了重写 14 15 @Override 16 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { 17 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { 18 Class<?> targetClass = config.getTargetClass(); 19 if (targetClass == null) { 20 throw new AopConfigException("TargetSource cannot determine target class: " + 21 "Either an interface or a target is required for proxy creation."); 22 } 23 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { 24 return new JdkDynamicAopProxy(config); 25 } 26 return new ObjenesisCglibAopProxy(config); 27 } 28 else { 29 return new JdkDynamicAopProxy(config); 30 } 31 }
从源码可以看出,spring中存在着两种代理JdkDynamicAopProxy和ObjenesisCglibAopProxy两种
看一下createAopProxy方法中影响这spring使用何种代理的判断条件,也就是if中的条件
(1)isOptimize
用来控制通过CGLIB创建的代理是否使用激进的优化策略。除非了解AOP代理如何处理优化,否则不推荐使用这个设置,目前这个属性仅用于CGLIB代理,JDK代理无效
(2)isProxyTargetClass
这个属性为true时,目标类本身被代理而不是目标类的接口,如果这个属性设置为true,CGLIB代理将被创建,设置方式<aop:aspectj-autoproxy proxy-target-class="true" />
(3)hasNoUserSuppliedProxyInterfaces
是否存在代理接口
JDK代理与CGLIB代理的总结:
如果目标对象实现了接口,默认情况下会使用JDK动态代理实现AOP
如果目标对象实现了接口,可以强制使用CGLIB实现AOP
如果目标对象没有实现接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB代理之前切换
(2)获取代理
JDK代理使用案例
1 // 创建业务接口,业务对外提供的接口,包含着业务可以对外提供的功能 2 public interface UserService{ 3 4 // 目标方法 5 public abstract void add(); 6 } 7 8 // 创建业务接口实现类 9 public class UserServiceImpl implements UserService { 10 11 public void add(){ 12 System.out.println("---------add()----------"); 13 } 14 } 15 16 // 创建自定义的InvocationHandler,用于对接口提供的方法进行增强 17 public class MyInvocationHandler implements InvocationHandler{ 18 private Object target; 19 20 public MyInvocationHandler(Object target){ 21 super(); 22 this.target = target; 23 } 24 25 // 执行目标对象方法 26 public Object invoke(Obejct proxy, Method method, Object[] args) throws Throwable { 27 System.out.println("---------before()----------"); 28 Obejct result = method.invoke(target, args); 29 System.out.println("---------after()----------"); 30 return result; 31 } 32 33 // 获取目标对象的代理对象 34 public Object getProxy(){ 35 return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this); 36 } 37 } 38 39 // 测试类 40 public class ProxyTest{ 41 42 @Test 43 public void testProxy(){ 44 UserService userService = new UserServiceImpl(); 45 // 实例化InvocationHandler 46 MyInvocationHandler invocationHandler = new MyInvocationHandler(userService); 47 // 根据目标对象生成代理对象 48 UserService proxy = (UserService) invocationHandler.getProxy(); 49 // 执行代理对象方法 50 proxy.add(); 51 } 52 }
用起来很简单,这其实就是AOP的简单的实现,在目标方法的执行之前和执行之后进行了增强,spring的AOP实现其实也就是用了Proxy、InvocationHandler这两个类
再次回顾一下使用JDK代理的方式,在整个创建过程中,对于InvocationHandler的创建是最为核心的,在自定义的InvocationHandler中需要重写三个函数
构造函数,将代理对象传入
invoke方法,此方法中实现了AOP增强的所有逻辑
getProxy方法
JdkDynamicAopProxy的getProxy()源码:
org.springframework.aop.framework.JdkDynamicAopProxy类中
1 @Override 2 public Object getProxy(@Nullable ClassLoader classLoader) { 3 if (logger.isDebugEnabled()) { 4 logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); 5 } 6 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); 7 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); 8 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 9 }
JDKProxy的使用关键是创建自定义的InvocationHandler,而InvocationHandler中包含了需要覆盖的函数getProxy,并且JdkDynamicAopProxy还实现了InvocationHandler接口,
因此,在该类中肯定存在一个重写的invoke方法,完成AOP的核心逻辑:invoke函数源码:
1 @Override 2 @Nullable 3 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 4 Object oldProxy = null; 5 boolean setProxyContext = false; 6 7 TargetSource targetSource = this.advised.targetSource; 8 Object target = null; 9 10 try { 11 // equals方法的处理 12 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { 13 // The target does not implement the equals(Object) method itself. 14 return equals(args[0]); 15 } 16 // hash方法的处理 17 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 18 // The target does not implement the hashCode() method itself. 19 return hashCode(); 20 } 21 else if (method.getDeclaringClass() == DecoratingProxy.class) { 22 // There is only getDecoratedClass() declared -> dispatch to proxy config. 23 return AopProxyUtils.ultimateTargetClass(this.advised); 24 } 25 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && 26 method.getDeclaringClass().isAssignableFrom(Advised.class)) { 27 // Service invocations on ProxyConfig with the proxy config... 28 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 29 } 30 31 Object retVal; 32 33 // 有时候目标对象内部的自我调用将无法实施切面中的增强,则需要此属性暴露代理 34 if (this.advised.exposeProxy) { 35 // Make invocation available if necessary. 36 oldProxy = AopContext.setCurrentProxy(proxy); 37 setProxyContext = true; 38 } 39 40 // Get as late as possible to minimize the time we "own" the target, 41 // in case it comes from a pool. 42 target = targetSource.getTarget(); 43 Class<?> targetClass = (target != null ? target.getClass() : null); 44 45 // Get the interception chain for this method. 46 // 获取当前方法的拦截器链 47 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 48 49 // Check whether we have any advice. If we don't, we can fallback on direct 50 // reflective invocation of the target, and avoid creating a MethodInvocation. 51 if (chain.isEmpty()) { 52 // We can skip creating a MethodInvocation: just invoke the target directly 53 // Note that the final invoker must be an InvokerInterceptor so we know it does 54 // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. 55 // 如果没有发现拦截器链,那么直接调用切点方法 56 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 57 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); 58 } 59 else { 60 // We need to create a method invocation... 61 // 将拦截器封装在ReflectiveMethodInvocation以便于其使用proceed进行链接表用拦截器 62 MethodInvocation invocation = 63 new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 64 // Proceed to the joinpoint through the interceptor chain. 65 // 执行拦截器链 66 retVal = invocation.proceed(); 67 } 68 69 // Massage return value if necessary. 70 // 返回结果 71 Class<?> returnType = method.getReturnType(); 72 if (retVal != null && retVal == target && 73 returnType != Object.class && returnType.isInstance(proxy) && 74 !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { 75 // Special case: it returned "this" and the return type of the method 76 // is type-compatible. Note that we can't help if the target sets 77 // a reference to itself in another returned object. 78 retVal = proxy; 79 } 80 else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { 81 throw new AopInvocationException( 82 "Null return value from advice does not match primitive return type for: " + method); 83 } 84 return retVal; 85 } 86 finally { 87 if (target != null && !targetSource.isStatic()) { 88 // Must have come from TargetSource. 89 targetSource.releaseTarget(target); 90 } 91 if (setProxyContext) { 92 // Restore old proxy. 93 AopContext.setCurrentProxy(oldProxy); 94 } 95 } 96 }
上面的方法中最主要的就是创建了一个拦截器链,并使用ReflectiveMethodInvocation类进行了封装,而在ReflectiveMethodInvocation的proceed中实现了拦截器的逐一
调用,那继续看proceed方法的源码,如何实现前置增强与后置增强的:
此方法是在org.springframework.aop.framework.ReflectiveMethodInvocation类中进行重写的:
1 @Override 2 @Nullable 3 public Object proceed() throws Throwable { 4 // We start with an index of -1 and increment early. 5 // 执行完所有增强后,执行切点方法 6 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 7 return invokeJoinpoint(); 8 } 9 10 // 获取下一个要执行的拦截器 11 Object interceptorOrInterceptionAdvice = 12 this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); 13 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { 14 // Evaluate dynamic method matcher here: static part will already have 15 // been evaluated and found to match. 16 // 动态匹配 17 InterceptorAndDynamicMethodMatcher dm = 18 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; 19 if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { 20 return dm.interceptor.invoke(this); 21 } 22 else { 23 // Dynamic matching failed. 24 // Skip this interceptor and invoke the next in the chain. 25 // 不匹配则不执行拦截器 26 return proceed(); 27 } 28 } 29 else { 30 // It's an interceptor, so we just invoke it: The pointcut will have 31 // been evaluated statically before this object was constructed. 32 /** 33 * 普通拦截器则直接调用拦截器 34 * 例如: 35 * MethodBeforeAdviceIntercepter 36 * AspectJAroundAdvice 37 * AspectJAfterAdvice 38 */ 39 // 将this作为参数传递以保证当前实例中调用链的执行 40 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 41 } 42 }
CGLIB代理使用案例
CGLIB是一个强大的高性能的代码生成包。CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
看如何使用CGLIB
需要导入外部net.sf.cglib.proxy包
1 public class EnhancerDemo{ 2 public static void main(String[] args){ 3 Enhancer enhancer = new Enhancer(); 4 enhancer.setSupperclass(EnhancerDemo.class); 5 enhancer.setCallback(new MethodInterceptorImpl()); 6 EnhancerDemo demo = (EnhancerDemo) enhancer.create(); 7 demo.test(); 8 System.out.println(demo); 9 } 10 11 public void test(){ 12 System.out.println("EnhancerDemo test()"); 13 } 14 15 public static class MethodInterceptorImpl implements MethodInterceptor{ 16 @Override 17 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy){ 18 System.out.println("Before invoke" + method); 19 Object result = proxy.invokeSuper(obj, args); 20 System.out.println("After invoke" + method); 21 return result; 22 } 23 } 24 }
完成CGLIB代理的类是委托给Cglib2AopProxy类去实现的,Cglib2AopProxy的入口应该是getProxy,也就是说Cglib2AopProxy类的getProxy中实现了Enhancer的创建和接口封装
我就有点搞不懂了,作者从哪里搞出来一个Cglib2AopProxy,明明是CglibAopProxy,看getProxy的源码
org.springframework.aop.framework.CglibAopProxy类中的getProxy
1 @Override 2 public Object getProxy(@Nullable ClassLoader classLoader) { 3 if (logger.isDebugEnabled()) { 4 logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); 5 } 6 7 try { 8 Class<?> rootClass = this.advised.getTargetClass(); 9 Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); 10 11 Class<?> proxySuperClass = rootClass; 12 if (ClassUtils.isCglibProxyClass(rootClass)) { 13 proxySuperClass = rootClass.getSuperclass(); 14 Class<?>[] additionalInterfaces = rootClass.getInterfaces(); 15 for (Class<?> additionalInterface : additionalInterfaces) { 16 this.advised.addInterface(additionalInterface); 17 } 18 } 19 20 // Validate the class, writing log messages as necessary. 21 // 验证Class 22 validateClassIfNecessary(proxySuperClass, classLoader); 23 24 // Configure CGLIB Enhancer... 25 // 创建和配置Enhancer 26 Enhancer enhancer = createEnhancer(); 27 if (classLoader != null) { 28 enhancer.setClassLoader(classLoader); 29 if (classLoader instanceof SmartClassLoader && 30 ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { 31 enhancer.setUseCache(false); 32 } 33 } 34 enhancer.setSuperclass(proxySuperClass); 35 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); 36 enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); 37 enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); 38 39 // 设置拦截器 40 Callback[] callbacks = getCallbacks(rootClass); 41 Class<?>[] types = new Class<?>[callbacks.length]; 42 for (int x = 0; x < types.length; x++) { 43 types[x] = callbacks[x].getClass(); 44 } 45 // fixedInterceptorMap only populated at this point, after getCallbacks call above 46 enhancer.setCallbackFilter(new ProxyCallbackFilter( 47 this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); 48 enhancer.setCallbackTypes(types); 49 50 // Generate the proxy class and create a proxy instance. 51 // 生成代理类和创建代理 52 return createProxyClassAndInstance(enhancer, callbacks); 53 } 54 catch (CodeGenerationException | IllegalArgumentException ex) { 55 throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + 56 ": Common causes of this problem include using a final class or a non-visible class", 57 ex); 58 } 59 catch (Throwable ex) { 60 // TargetSource.getTarget() failed 61 throw new AopConfigException("Unexpected AOP exception", ex); 62 } 63 }
以上函数完成的说明了spring中创建Enhancer的过程,这里最重要的是getCallbacks设置拦截器链,看getCallbacks的源码:
org.springframework.aop.framework.CglibAopProxy类中:
1 private Callback[] getCallbacks(Class<?> rootClass) throws Exception { 2 // Parameters used for optimization choices... 3 // 对expose-proxy属性的处理 4 boolean exposeProxy = this.advised.isExposeProxy(); 5 boolean isFrozen = this.advised.isFrozen(); 6 boolean isStatic = this.advised.getTargetSource().isStatic(); 7 8 // Choose an "aop" interceptor (used for AOP calls). 9 // 将拦截器封装在DynamicAdvisedInterceptor中 10 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); 11 12 // Choose a "straight to target" interceptor. (used for calls that are 13 // unadvised but can return this). May be required to expose the proxy. 14 Callback targetInterceptor; 15 if (exposeProxy) { 16 targetInterceptor = (isStatic ? 17 new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : 18 new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource())); 19 } 20 else { 21 targetInterceptor = (isStatic ? 22 new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : 23 new DynamicUnadvisedInterceptor(this.advised.getTargetSource())); 24 } 25 26 // Choose a "direct to target" dispatcher (used for 27 // unadvised calls to static targets that cannot return this). 28 Callback targetDispatcher = (isStatic ? 29 new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp()); 30 31 Callback[] mainCallbacks = new Callback[] { 32 // 将拦截器链加入到Callback中 33 aopInterceptor, // for normal advice 34 targetInterceptor, // invoke target without considering advice, if optimized 35 new SerializableNoOp(), // no override for methods mapped to this 36 targetDispatcher, this.advisedDispatcher, 37 new EqualsInterceptor(this.advised), 38 new HashCodeInterceptor(this.advised) 39 }; 40 41 Callback[] callbacks; 42 43 // If the target is a static one and the advice chain is frozen, 44 // then we can make some optimizations by sending the AOP calls 45 // direct to the target using the fixed chain for that method. 46 if (isStatic && isFrozen) { 47 Method[] methods = rootClass.getMethods(); 48 Callback[] fixedCallbacks = new Callback[methods.length]; 49 this.fixedInterceptorMap = new HashMap<>(methods.length); 50 51 // TODO: small memory optimization here (can skip creation for methods with no advice) 52 for (int x = 0; x < methods.length; x++) { 53 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); 54 fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( 55 chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); 56 this.fixedInterceptorMap.put(methods[x].toString(), x); 57 } 58 59 // Now copy both the callbacks from mainCallbacks 60 // and fixedCallbacks into the callbacks array. 61 callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; 62 System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); 63 System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); 64 this.fixedInterceptorOffset = mainCallbacks.length; 65 } 66 else { 67 callbacks = mainCallbacks; 68 } 69 return callbacks; 70 }
在getCallbacks中spring考虑了很多情况,但是对于我们来说,只需要理解最常用的就可以了,比如将advised属性封装在DynamicAdvisedInterceptor并加入在
callbacks中,这么做的目的是什么,为什么会这么做?在前面的示例中,我们了解到CGLIB中对于方法的拦截是通过将自定义的拦截器(实现MethodInterceptor接口)加入
Callback中并在调用代理的时候直接激活拦截器中的intercept方法来实现的,那么在getCallback中正是实现了这样的一个目的,DynamicAdvisedInterceptor继承自MethodInterceptor
加入CallBack中后,再次调用代理时会直接调用DynamicAdvisedInterceptor中的intercept方法,所以,由此推断,对于CGLIB方式实现的代理,其核心逻辑在
DynamicAdvisedInterceptor中的intercept方法,DynamicAdvisedInterceptor作为CglibAopProxy内部封装私有类,其在org.springframework.aop.framework.CglibAopProxy类中:
1 @Override 2 @Nullable 3 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 4 Object oldProxy = null; 5 boolean setProxyContext = false; 6 Object target = null; 7 TargetSource targetSource = this.advised.getTargetSource(); 8 try { 9 if (this.advised.exposeProxy) { 10 // Make invocation available if necessary. 11 oldProxy = AopContext.setCurrentProxy(proxy); 12 setProxyContext = true; 13 } 14 // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool... 15 target = targetSource.getTarget(); 16 Class<?> targetClass = (target != null ? target.getClass() : null); 17 // 获取拦截链 18 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 19 Object retVal; 20 // Check whether we only have one InvokerInterceptor: that is, 21 // no real advice, but just reflective invocation of the target. 22 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { 23 // We can skip creating a MethodInvocation: just invoke the target directly. 24 // Note that the final invoker must be an InvokerInterceptor, so we know 25 // it does nothing but a reflective operation on the target, and no hot 26 // swapping or fancy proxying. 27 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 28 // 如果拦截链为空则直接激活原方法 29 retVal = methodProxy.invoke(target, argsToUse); 30 } 31 else { 32 // We need to create a method invocation... 33 // 进入链中 34 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); 35 } 36 retVal = processReturnType(proxy, target, method, retVal); 37 return retVal; 38 } 39 finally { 40 if (target != null && !targetSource.isStatic()) { 41 targetSource.releaseTarget(target); 42 } 43 if (setProxyContext) { 44 // Restore old proxy. 45 AopContext.setCurrentProxy(oldProxy); 46 } 47 } 48 }
上述的实现与JDK方式实现代理中的invoke方法基本相同,都是首先构造链,然后封装此链进行串联调用,区别就是在JDK代理中直接构造ReflectiveMethodInvocation类,而在
CGLIB代理中使用CglibMethodInvocation,CglibMethodInvocation继承自ReflectiveMethodInvocation,但是process方法没有重写
注意:spring还支持静态代理,这里没有写!!!不想写了
来源:https://www.cnblogs.com/ssh-html/p/11296363.html