在上篇文章 Spring AOP 注解方式源码解析 中已经获取到了 bean 的对应加强器,以后,就能够建立对应的代理了,Spring AOP 底层使用的是 JDK 动态代理和 CGLIB 的代理,在什么状况下使用JDK动态代理,何时使用 CGLIB 代理呢,下面经过源码来看一下this
// AbstractAutoProxyCreator.java protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //...... // 获取的加强器 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 建立代理 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } //............ return bean; }
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, Object[] specificInterceptors, TargetSource targetSource) { // .... ProxyFactory proxyFactory = new ProxyFactory(); //复制当前类的一些属性 proxyFactory.copyFrom(this); // 若是在配置文件中配置的aop标签的属性proxy-target-class为false, if (!proxyFactory.isProxyTargetClass()) { // 是否须要代理当前类而不是代理接口,根据preserveTargetClass属性来判断Boolean.TRUE.equals(bd.getAttribute("preserveTargetClass") if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { // 若是代理的是接口,则添加代理接口 evaluateProxyInterfaces(beanClass, proxyFactory); } } // 对加强器进行包装,有些加强是经过拦截器等方式来实现的,因此这里统一封装为 Advisor 进行处理 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); // 加入加强器 proxyFactory.addAdvisors(advisors); // 设置要代理的类 proxyFactory.setTargetSource(targetSource); // 用户自定义代理 customizeProxyFactory(proxyFactory); // 该属性用来控制代理工厂被配置之后,是否还容许修改通知,默认为false proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 建立代理 return proxyFactory.getProxy(getProxyClassLoader()); } // 添加接口代理 protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) { Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader()); boolean hasReasonableProxyInterface = false; //.... if (hasReasonableProxyInterface) { for (Class<?> ifc : targetInterfaces) { proxyFactory.addInterface(ifc); } } else { proxyFactory.setProxyTargetClass(true); } }
封装加强,在Spring中,有些加强是经过拦截器来实现的,因此这里统一封装为 Advisor 进行处理,对应方法 buildAdvisors():lua
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) { //解析全部的 InterceptorName Advisor[] commonInterceptors = resolveInterceptorNames(); List<Object> allInterceptors = new ArrayList<>(); if (specificInterceptors != null) { // 添加参数传进来的,即咱们自定义的加强 allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors.length > 0) { // 添加拦截器 if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } //把拦截器包装为Advisor Advisor[] advisors = new Advisor[allInterceptors.size()]; for (int i = 0; i < allInterceptors.size(); i++) { // wrap包装 advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); } return advisors; } //wrap包装 // 仅仅对 Advisor 和 Advice进行包装 public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { // 若是原本就是 Advisor,则直接返回 if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } // 类型不正确,异常 if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // MethodInterceptor 类型使用 DefaultPointcutAdvisor 封装 return new DefaultPointcutAdvisor(advice); } // 若是存在 Advisor 的适配器,也须要包装 for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); }
建立代理getProxyspa
return proxyFactory.getProxy(getProxyClassLoader()); public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
在这里会判断代理建立的方式,是使用 JDK 的动态代理仍是 CGLIB 的代理。.net
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //这里初步判断代理的建立方式,若是不知足则直接使用 JDK 动态代理,若是知足条件,则进一步在判断是否使用 JKD 动态代理仍是 CGLIB 代理 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("......"); } // 若是代理的是接口或者设置代理的类就是当前类,则使用 JDK 动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 不然使用 CGLIB 代理 return new ObjenesisCglibAopProxy(config); } // 条件不知足CGBLIB的方式直接使用JDK动态代理 else { return new JdkDynamicAopProxy(config); } }
这里的 if 条件有三个:代理
1. config.isOptimize() : 用来控制经过 CGLIB 建立的代理是否使用激进的优化策略,目前仅用于 CGLIB 代理
2. config.isProxyTargetClass() : 在 Spring AOP 功能使用详解 中了解到,咱们能够强制 Spring 彻底使用 CGLIB 进行代理,只要在配置文件配置 proxy-target-class 属性为true便可,如:<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/>,若是配置个该属性,则会使用 CGLIB 来建立代理
3. hasNoUserSuppliedProxyInterfaces(config) : 是否存在代理接口,若是不存在代理接口,则使用 CGLIB 进行代理
若是这三个条件有一个知足,则会再进一次判断,须要代理的类是不是接口或者是否设置的就是代理当前类,若是是,则仍是会使用 JDK 动态代理,不然的话才会使用 CGLIB 代理。
若是代理类实现了接口,则Spring默认使用 JDK 动态代理,但能够设置强制使用 CGLIB 代理
JDK 动态代理只能代理接口而不能代理类
CGLIB 代理类,经过继承的方式,为目标类生成子类,并重写方法来实现代理,它不能代理final的类或方法
关于 JDK 动态代理和 CGLIB 代理的使用方式能够参考 Spring AOP 功能使用详解
接下来看下 JDK 动态代理和 CGLIB 代理的建立过程:
return new JdkDynamicAopProxy(config); // JdkDynamicAopProxy.java public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { this.advised = config; }
经过 JDK 动态代理来获取代理的方法 getProxy():
public Object getProxy(@Nullable ClassLoader classLoader) { // 获取代理类的接口 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); // 处理 equals , hashcode 方法 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 建立代理 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
能够看到,Spring 使用 JDK 建立代理和咱们使用的 JDK 来建立代理是没有区别的,都是使用 Proxy.newProxyInstance 的方式来建立;咱们知道 JDK 动态代理有个 invoke 方法,用来执行目标方法,而 JdkDynamicAopProxy 实现了 InvocationHandler 接口,全部它也会重写该方法,在该方法中植入加强:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; // 目标类 TargetSource targetSource = this.advised.targetSource; Object target = null; try { // 若是接口没有定义 equals 方法且当前方法是 equals 方法,则不会加强,直接返回 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // 若是接口没有定义 hashCode方法且当前方法是 hashCode方法,则不会加强,直接返回 return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // 若是方法所在的类和Advised是同一个类或者是父类子类关系,则直接执行 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } // 返回值 Object retVal; // 这里对应的是expose-proxy属性的应用,把代理暴露处理 // 目标方法内部的自我调用将没法实施切面中的加强,因此在这里须要把代理暴露出去 if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // 获取该方法的拦截器 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //若是方法的拦截器为空,则直接执行目标方法,避免建立 MethodInvocation 对象 if (chain.isEmpty()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); // 执行目标方法:method.invoke(target, args) retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 把全部的拦截器封装在ReflectiveMethodInvocation中,以便于链式调用 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 执行拦截器链 retVal = invocation.proceed(); } // .......... return retVal; } finally { // . } }
在执行拦截器方法 proceed 中执行加强方法,好比前置加强在方法以前执行,后置加强在方法以后执行,proceed 方法以下:
public Object proceed() throws Throwable { //当执行完全部加强方法后执行目标方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { // method.invoke(target, args) return invokeJoinpoint(); } // 获取下一个要执行的拦截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // 动态匹配 InterceptorAndDynamicMethodMatcher dm = interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); // 若是可以匹配,则执行拦截器的方法, if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { // 好比 @After @Before 对应的加强器(拦截器)的方法 // 好比 @After 对应的加强器 AspectJAfterAdvice 的invoke方法为:MethodInvocation.proceed(); return dm.interceptor.invoke(this); } else { // 若是动态匹配失败,则跳过该拦截器,执行下一个拦截器 return proceed(); } } else { // 普通拦截器,直接调用 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
在该方法中完成了加强的植入,主要逻辑就是,每一个方法都会有一个拦截器链,在 AOP 中咱们称之为加强,而后循环执行每一个拦截器链,当执行完全部的拦截器后,才会执行目标方法。好比 @After 对应的加强器AspectJAfterAdvice, @Around 对应的加强器AspectJAroundAdvice等。
以上就是 Spring 经过 JDK 动态代理来实现 AOP 的一个过程。
ObjenesisCglibAopProxy 继承于 CglibAopProxy
return new ObjenesisCglibAopProxy(config) public CglibAopProxy(AdvisedSupport config) throws AopConfigException { this.advised = config; this.advisedDispatcher = new AdvisedDispatcher(this.advised); }
CglibAopProxy 的 getProxy 方法以下:
public Object getProxy(@Nullable ClassLoader classLoader) { // 代理的目标类 Class<?> rootClass = this.advised.getTargetClass(); Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // 建立并配置 CGLIB 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); // 设置拦截器 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); //生成代理类和建立代理 return createProxyClassAndInstance(enhancer, callbacks); } // 生成代理类和建立代理 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()); }
从上述的方法可知,Sping 使用 CGLIB 来建立代理类和代理对象和咱们使用的同样,都是使用 Enhancer.create() 来建立,这里主要的是设置拦截器,经过 getCallbacks () 方法来实现的,以下:
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { //expose-proxy 属性 boolean exposeProxy = this.advised.isExposeProxy(); boolean isFrozen = this.advised.isFrozen(); boolean isStatic = this.advised.getTargetSource().isStatic(); // 将拦截器封装在 DynamicAdvisedInterceptor 中 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); //暴露代理 Callback targetInterceptor; if (exposeProxy) { targetInterceptor = (isStatic ? new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource())); } else { targetInterceptor = (isStatic ? new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedInterceptor(this.advised.getTargetSource())); } // 将拦截器 aopInterceptor 进入到 Callback 中 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) }; // .............. return callbacks; }
咱们知道使用 CGLIB 来实现代理功能的时候,当代理执行的时候,会调用 intercept 方法,和 JKD 动态代理的 invoke 方法相似;Spring 中 CGLIB 的 intercept 方法以下,该方法在 DynamicAdvisedInterceptor 中,从上面的代理知道,使用它来封装拦截器,它是 CglibAopProxy 的一个子类:
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy){ Object oldProxy = null; boolean setProxyContext = false; Object target = null; // 目标类 TargetSource targetSource = this.advised.getTargetSource(); // 处理 expose-proxy 属性,暴露代理 if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // 获取拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 返回值 Object retVal; if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); // 若是拦截器为空则直接执行目标方法 retVal = methodProxy.invoke(target, argsToUse); } else { //封装拦截器链并执行 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } // 处理返回值类型 retVal = processReturnType(proxy, target, method, retVal); return retVal; // ..................... }
CGLIB 使用 CglibMethodInvocation 来封装拦截器链,它是 CglibAopProxy 的一个内部类:
private static class CglibMethodInvocation extends ReflectiveMethodInvocation { @Nullable private final MethodProxy methodProxy; public CglibMethodInvocation(Object proxy, Object target, Method method,Object[] arguments, Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) { super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers); this.methodProxy = (Modifier.isPublic(method.getModifiers()) && method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) && !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ? methodProxy : null); } // proceed 方法会调用该方法来执行 @Override protected Object invokeJoinpoint() throws Throwable { if (this.methodProxy != null) { return this.methodProxy.invoke(this.target, this.arguments); } else { return super.invokeJoinpoint(); } } }
当调用 proceed 方法时,和 JDK 的处理是同样的,只不过当执行完全部的拦截器后,执行目标方法调用的是 CglibMethodInvocation 的 invokeJoinpoint 来执行而已;由于 CglibMethodInvocation 继承于 ReflectiveMethodInvocation ,而 JDK 使用的就是 ReflectiveMethodInvocation 来执行的,ReflectiveMethodInvocation 的 invokeJoinpoint 方法为 : method.invoke(target, args)
以上就是 Spring 使用 JDK 动态代理和 CGLIB 代理来实现 AOP 的原理。