接着上一篇中的内容!
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