思考:springAOP底层运用了什么设计模式?算法
生成代理类:代理设计模式、底层五个通知造成调用链采用:责任链设计模式spring
下面咱们回顾下SpringAop实现流程:设计模式
一、配置@EnableAspectJAutoProxy:开启AOP权限ide
二、@Import(AspectJAutoProxyRegistrar.class):往IOC容器中注入SpringAOP切面类函数
三、registerAspectJAnnotationAutoProxyCreatorIfNecessary():注册切面类源码分析
四、AnnotationAwareAspectJAutoProxyCreator.class:注册到IOC容器中,【AOP的入口】post
五、AnnotationAwareAspectJAutoProxyCreator:祖宗是BeanPostProcessor接口,而实现BeanPostProcessor接口后,当Spring加载这个Bean会在实例化前调用其后置处理器实现加强ui
六、postProcessAfterInitialization:后置处理器【AOP实现核心逻辑】this
####6.一、wrapIfNecessary()判断该对象是否在AOP的扫包范围内,真正建立代理类的地方lua
#########6.1.一、getAdvicesAndAdvisorsForBean建立代理对象包括获取加强方法和根据获取的加强进行代理
#########6.1.二、createAopProxy()判断被代理类是否实现了接口,若是有实现了接口的化,是采用JDK动态代理,不然状况下就使用CGLIB代理
####6.二、根据条件判断使用JdkDynamicAopProxy或者JdkDynamicAopProxy方法实现代理
####6.三、最终执行目标方法的时候,就会进入到JdkDynamicAopProxy 的invoke方法或者JdkDynamicAopProxy的intercept方法
####6.五、底层使用集合存放使用通知,而后再使用责任链设计模式循环的调用
咱们先来总结下JDK和CGLIB方式
- 若是目标对象实现了接口,默认状况下会采用JDK的动态代理实现AOP
- 若是目标对象实现了接口,能够强制使用CGLIB实现AOP
- 若是目标对象没有实现接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换
JDK动态代理和CGLIB字节码生成的区别?
JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,由于是继承,因此该类或者方法最好不要声明为final
1.JDK代理使用示例
public interface UserService { //目标方法 public abstract void add(); }
public class UserServiceImpl implements UserService { /** * dynamic.proxy.UserService#add() */ public void add() { System.out.println("add......."); } }
public class MyInvocationHandler implements InvocationHandler { //目标对象 private Object target; /** * 构造函数 * @param target:目标对象 */ public MyInvocationHandler(Object target) { super(); this.target = target; } /** * 执行目标对象的方法 * @param proxy * @param method * @param args * @return * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("-------------before-----------"); Object result = method.invoke(target, args); System.out.println("-------------after------------"); return result; } public Object getProxy(){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(),this); } }
public class ProxyTest { public static void main(String[] args) { //实例化目标对象 UserService userService = new UserServiceImpl(); //实例化InvocationHandler MyInvocationHandler invocationHandler = new MyInvocationHandler(userService); //根据目标对象生成代理对象 UserService proxy = (UserService) invocationHandler.getProxy(); //调用代理对象的方法 proxy.add(); } }
输出结果:
咱们再次回顾下JDK代理方式,在整个建立过程当中,对于InvocationHandler的建立是最为核心的,在自定义的InvocationHandler中须要重写三个函数
构造函数,将代理的对象传入
invoke方法,此方法中实现了AOP加强的全部逻辑
getProxy方法,此方法千篇一概,可是必不可少。
那么咱们看看Spring中的JDK代理实现是否是也是这么作的呢?继续以前的跟踪,到达JdkDynamicAopProxy的getProxy方法。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) { Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//若是循环遍历找到须要代理的对象,则会进入到这里建立代理 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } }
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 (this.shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { this.evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); this.customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (this.advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.getProxyClassLoader()); }
获取了五个通知:
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
咱们能够推断出,在JdkDynamicAopProxy中必定会有个invoke函数,而且JdkDynamicAopProxy会把AOP的核心逻辑写在里面。咱们查看代码发现确实是有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; Class var9; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { Boolean var19 = this.equals(args[0]); return var19; } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { Integer var18 = this.hashCode(); return var18; } if (method.getDeclaringClass() != DecoratingProxy.class) { Object retVal; if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); return retVal; } //有时候目标对象内部的自我调用将没法实施切面中的加强则须要经过此属性暴露代理 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); if (chain.isEmpty()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); //若是没有发现任何拦截器那么直接调用切点方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //将拦截器封装在ReflectiveMethodInvocation,以便于使用其proceed进行连接 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //执行拦截器链 retVal = invocation.proceed(); } Class<?> returnType = method.getReturnType(); //返回结果 if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; } 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); } Object var13 = retVal; return var13; .... }
上面函数中主要是 建立了一个拦截器链,并使用ReflectiveMethodInvocation类进行了链的封装,而在ReflectiveMethodInvocation类的proceed方法中是怎么实现前置加强和后置加强
public Object proceed() throws Throwable { if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return this.invokeJoinpoint(); } else { //获取下一个须要执行的拦截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { //动态匹配 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice; //匹配则执行拦截器,不匹配不执行拦截器 return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed(); } else { //普通拦截,直接调用拦截器,将this做为参数传递以保证当前实例中调用链的执行 return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this); } } }
在proceed方法中,ReflectiveMethodInvocation中的主要职责是维护了连接调用的计数器,记录当前调用连接的位置,以便链能够有序的进行下去。
public class EnhancerDemo { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(EnhancerDemo.class); enhancer.setCallback(new MethodInterceptorImpl()); EnhancerDemo demo = (EnhancerDemo) enhancer.create(); demo.test(); System.out.println(demo); } private void test() { System.out.println("EnhancerDemo #test()...."); } private static class MethodInterceptorImpl implements MethodInterceptor{ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("------before invoke----"+method); Object result = methodProxy.invokeSuper(o, objects); System.out.println("-----after invoke------"+method); return result; } } }
运行结果
生成的对象为:com.xiaoxu.cglib.EnhancerDemo$$EnhancerByCGLIB$$c9092bbe@78e03bb5的实例,这个类是运行时由CGLIB产生的。
咱们看下Spring源码对CGLIB的实现:
public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + 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; int x; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); Class[] var5 = additionalInterfaces; int var6 = additionalInterfaces.length; for(x = 0; x < var6; ++x) { Class<?> additionalInterface = var5[x]; this.advised.addInterface(additionalInterface); } } //验证class this.validateClassIfNecessary(proxySuperClass, classLoader); //建立及配置Enhancer Enhancer enhancer = this.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 CglibAopProxy.ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); //设置拦截器 Callback[] callbacks = this.getCallbacks(rootClass); Class<?>[] types = new Class[callbacks.length]; for(x = 0; x < types.length; ++x) { types[x] = callbacks[x].getClass(); } enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); return this.createProxyClassAndInstance(enhancer, callbacks); } catch (IllegalArgumentException | CodeGenerationException var9) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: Common causes of this problem include using a final class or a non-visible class", var9); } catch (Throwable var10) { throw new AopConfigException("Unexpected AOP exception", var10); } }
这里最重要的是经过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 CglibAopProxy.DynamicAdvisedInterceptor(this.advised); Object targetInterceptor; if (exposeProxy) { targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); } else { targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedInterceptor(this.advised.getTargetSource()); } Callback targetDispatcher = isStatic ? new CglibAopProxy.StaticDispatcher(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.SerializableNoOp(); Callback[] mainCallbacks = new Callback[]{aopInterceptor, (Callback)targetInterceptor, new CglibAopProxy.SerializableNoOp(), (Callback)targetDispatcher, this.advisedDispatcher, new CglibAopProxy.EqualsInterceptor(this.advised), new CglibAopProxy.HashCodeInterceptor(this.advised)}; Callback[] callbacks; if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap(methods.length); for(int x = 0; x < methods.length; ++x) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = new CglibAopProxy.FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(methods[x].toString(), x); } //将拦截器加入到Callback中 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; }
在getCallbacks中spring考虑了不少状况,可是对于咱们来讲,只须要理解最经常使用的就能够了,CGLIB中对于方法的拦截是经过将自定义的拦截器(实现MethodInterceptor接口)加入到Callback中
并在调用代理时直接激活拦截器中的intercept方法来实现。由此可推断,对于CGLIB方式实现的代理,其核心逻辑必然在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(); Object var16; try { 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 CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed(); } retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal); var16 = retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } return var16; }
上述的实现与JDK方式实现代理中的invoke方法大同小异,首先是构造链,而后封装此链进行串联调用,区别在于JDK中直接构造ReflectiveMethodInvocation,而在CGLIB中使用CglibMethodInvocation.
CglibMethodInvocation继承自ReflectiveMethodInvocation,可是process方法并无重写。
主要靠的是后置处理器BeanPostProcessor:在Bean对象初始化先后作一些加强
AnnotationAwareAspectJAutoProxyCreator的祖宗是BeanPostProcessor
【0】环绕通知以前执行→【1】前置通知→目标方法→【2】后置通知→【3】环绕通知以后执行
责任链设计模式,底层经过递归算法+责任链
如何存放起来:使用集合存放这些通知,集合当中不存放咱们的方法,只存放链,那么如何插入咱们的目标方法?
public interface MethodInterceptor { /** * 定义共同通知骨架 */ public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException; }
public class BeforMethodInterceptor implements MethodInterceptor { public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException { System.out.println(">>>>前置通知<<<<"); // 执行咱们的目标方法 methodInvocation.process();// 递归调用 } }
public class AfterMethodInterceptor implements MethodInterceptor { public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException { // 执行咱们的前置通知 methodInvocation.process(); System.out.println(">>>后置通知<<<"); } }
public class AroundMethodInterceptor implements MethodInterceptor { public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException { System.out.println("环绕通知在目标方法以前执行.."); methodInvocation.process(); System.out.println("环绕通知在目标方法以后执行.."); } }
public class UserService { public void login(String userName, Integer age) { System.out.println("userName:" + userName + ",age:" + age); } }
MethodInvocation 可以把链串起来
public interface MethodInvocation { //调用链造成 public void process() throws InvocationTargetException, IllegalAccessException; }
public class DefaultMethodInvacation implements MethodInvocation { /** * 存放全部的通知 */ private List<MethodInterceptor> listMethodInterceptor; private Object target;// 目标对象 private Method method;// 目标方法 private Object args[];// 目标参数 // 最终使用反射机制执行目标方法 private int index;// 记录当前链调用的位置 public DefaultMethodInvacation(List<MethodInterceptor> listMethodInterceptor, Object target, Method method, Object[] args) { this.listMethodInterceptor = listMethodInterceptor; this.target = target; this.method = method; this.args = args; } /** * 调用链造成 */ @Override public void process() throws InvocationTargetException, IllegalAccessException { if (index == listMethodInterceptor.size()) { method.invoke(target, args); // 执行目标 return; } MethodInterceptor methodInterceptor = listMethodInterceptor.get(index++); methodInterceptor.invoke(this); } }
执行结果:
>>>>前置通知<<<<
环绕通知在目标方法以前执行..
userName:mayikt,age:12
环绕通知在目标方法以后执行..
>>>后置通知<<<
参考书籍:Spring源码深度解析