本文剖析Spring AOP和动静代理原理和实现,Spring版本: 5.2.3.RELEASE
动静代理
1.1 代理模式
代理模式也叫做委托模式,它是一种根本的设计模式,其作用是提供委派角色以管制对实在对象的拜访。典型的代理模式通常蕴含一下三类角色
- 形象角色:它的作用是定义一组行为规范。形象角色个别出现为接口或抽象类
- 实在角色:也叫做被委托角色、被代理角色
- 代理角色:也叫做委托类,代理角色须要实现形象角色所定义的行为(即代理类须要实现形象角色所定义的接口),并且在实现接口办法的时候须要调用实在角色的相应办法
动态代理类依赖于实在类,对每一个实在类作代理都须要对应一个代理类,动态代理大量应用会导致类的急剧收缩,区别于动态代理在编译期确定代理类和实在类的关系并且生成代理类。动静代理则是在运行期利用JVM的反射机制生成代理类的字节码,并通过类加载器载入执生成代理对象
1.2 JDK动静代理
JDK动静代理是在运行时借助Proxy工具类静态方法创立实现了一组特定接口的代理类和对象,Proxy类是所有被创立的动静代理类的父类,每一个动静代理对象都会与特定的InvocationHandler对象绑定,对任意代理对象实现的接口办法的调用都会最终委派给InvocationHandler#invoke办法
// 定义形象角色接口public interface Subject { void sayHello(String name);}// 接口实现public class RealSubject implements Subject { @Override public void sayHello(String name){ System.out.println("hello, "+ name); }}// 编写调用解决类,实现invoke办法(加强逻辑的入口)public class MyInvocationHandler implements InvocationHandler { private Subject subject; MyInvocationHandler(Subject subject){ this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ //前置解决 System.out.println("Before method invoke..."); Object obj = method.invoke(subject, args); //后置解决 System.out.println("After method invoke..."); return obj; }}// 测试方法public class Client{ public static void main(String[] args) { Subject realSubject = new RealSubject(); MyInvocationHandler handler = new MyInvocationHandler(realSubject); Subject proxy = (Subject)Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); proxy.sayHello("world"); }运行后果:Before method invoke...hello, worldAfter method invoke...
从运行后果能够看出,对代理对象办法的调用会进入到自定义MyInvocationHandler#invoke办法,并在指标办法执行前后打印出了日志。将Proxy类生成的代理类通过反编译失去如下类文件,能够看到RealSubjectProxy继承自Proxy且实现了Subject接口,它定义了4个办法m0,m1,m2,m3,其中办法m3是对Subject接口sayHello办法的实现
public final class RealSubjectProxy extends Proxy implements Subject { private static Method m1; private static Method m3; private static Method m2; private static Method m0; public RealSubjectProxy(InvocationHandler var1) throws { super(var1); } // 代理办法 public final void sayHello(String var1) throws { try { // 将办法解决委派给父类InvocationHandler#invoke办法 super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } static { try { //m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m3 = Class.forName("com.example.demo.proxy.Subject").getMethod("sayHello", Class.forName("java.lang.String")); //m2 = Class.forName("java.lang.Object").getMethod("toString"); //m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } }}// Proxy类带参构造函数public class Proxy implements java.io.Serializable { protected InvocationHandler h; protected Proxy(InvocationHandler h) { Objects.requireNonNull(h); this.h = h; }}
Proxy类对外提供了4个静态方法,别离为
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces);public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);public static boolean isProxyClass(Class<?> cl);public static InvocationHandler getInvocationHandler(Object proxy);
newProxyInstance通过给定类加载器和接口生成代理对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } // 获取代理类 Class<?> cl = getProxyClass0(loader, intfs); try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } // 获取带参数InvocationHandler的结构器 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } // 反射创立代理对象 return cons.newInstance(new Object[]{h}); } // 省略 }
getProxyClass获取代理类对象
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException { final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } return getProxyClass0(loader, intfs); } private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // 如果缓存蕴含给定类加载器创立并且实现了特定接口的代理类,则返回该代理类; 否则动态创建此代理类对象 return proxyClassCache.get(loader, interfaces); }
1.2 Cglib动静代理
JDK动静代理尽管简略易用,然而其只能对实现了接口的类进行代理,而CGLIB以继承的形式动静生成一个被代理类的子类为没有实现接口的类提供代理,为JDK的动静代理提供了很好的补充。CGLIB原理是底层应用了ASM来操作字节码生成新的类,子类重写被代理的类的所有非final的办法。在子类中通过办法拦截器拦挡所有父类办法的调用,织入横切逻辑解决。// 定义Target类
public class Subject {
public void sayHello() { System.out.println("hello, world!");}
}
// 定义方法拦截器
public class LogInterceptor implements MethodInterceptor {
@Overridepublic Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable{ System.out.println("before ..."); Object result = methodProxy.invokeSuper(object, args); System.out.println("after ..."); return result;} }
public class CglibClient {
public static void main(String[] args) { Enhancer enhancer = new Enhancer(); // 设置超类,Cglib通过继承实现 enhancer.setSuperclass(Subject.class); // 设置办法拦截器回调援用,对于代理类上所有办法的调用,都会调用CallBack,而Callback则须要实现intercept() 办法进行拦挡 enhancer.setCallback(new LogInterceptor()); // 创立cglib 代理类
Subject proxy = (Subject)enhancer.create();
proxy.sayHello();}
}
控制台输入:
before ...
hello, world!
after ...Cglib动静代理对象生成Enhancer是CGLIB的字节码增强器,代理类创立入口在Enhancer#create办法,生成代理类的二进制字节码文件;加载二进制字节码,生成Class对象;通过反射机制取得实例结构器并创立代理类对象,在实例化代理类对象时执行动态代码块创立MethodProxypublic Object create() {
classOnly = false; argumentTypes = null; return createHelper();} private Object createHelper() { validate(); if (superclass != null) { //设置生成类的名称 setNamePrefix(superclass.getName()); } else if (interfaces != null) { //设置生成类的名称 setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName()); } //生成代理类对象(AbstractClassGenerator#newInstance办法中生成代理类的二进制字节码文件以及加载二进制字节码) return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, ReflectUtils.getNames(interfaces), filter, callbackTypes, useFactory, interceptDuringConstruction, serialVersionUID));}Cglib创立代理对象会产生如下3个Class文件
首先来看Cglib生成的代理类Subject$$EnhancerByCGLIB$$bc785f22.class,代理类在实例化时会执行其静态方法块,期间会给代理类的成员办法创立一个MethdProxy对象,比方办法CGLIB$sayHello$0与CGLIB$sayHello$0$Proxy,MethdProxy会在拦截器履行被调用public class Subject$$EnhancerByCGLIB$$bc785f22 extends Subject implements Factory { private MethodInterceptor CGLIB$CALLBACK_0; //拦截器 private static final Method CGLIB$sayHello$0$Method; //指标办法 private static final MethodProxy CGLIB$sayHello$0$Proxy; //代理办法 // ...省略 static void CGLIB$STATICHOOK1() { // 加载生成的代理类Class对象 Class var0 = Class.forName("com.example.demo.proxy.cglib.Subject$$EnhancerByCGLIB$$bc785f22"); // 指标类(Subject)Class对象 Class var1; // 通过反射获取指标类办法sayHello CGLIB$sayHello$0$Method = ReflectUtils.findMethods(new String[]{"sayHello", "()V"}, (var1 = Class.forName("com.example.demo.proxy.cglib.Subject")).getDeclaredMethods())[0]; // 创立MethodProxy CGLIB$sayHello$0$Proxy = MethodProxy.create(var1, var0, "()V", "sayHello", "CGLIB$sayHello$0"); } // 在拦截器中执行methodProxy.invokeSuper会进入这里 final void CGLIB$sayHello$0() { super.sayHello(); } public final void sayHello() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy); } else { super.sayHello(); } } // ...省略 }创立MethdProxy对象剖析,次要是实例化MethodProxy 和CreateInfo对象,CreateInfo用于拦截器执行时创立FastClass实例public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
MethodProxy proxy = new MethodProxy(); // 指标类sayHello办法签名 proxy.sig1 = new Signature(name1, desc); // 代理类CGLIB$sayHello$0办法签名 proxy.sig2 = new Signature(name2, desc); // 创立createInfo(CreateInfo是MethodProxy的一个外部类),用来保留类等信息 proxy.createInfo = new CreateInfo(c1, c2); return proxy;
}
private static class CreateInfo {
// 指标类Subject Class c1; // 代理类Subject$$EnhancerByCGLIB$$bc785f22 Class c2; NamingPolicy namingPolicy; GeneratorStrategy strategy; boolean attemptLoad; public CreateInfo(Class c1, Class c2) { this.c1 = c1; this.c2 = c2; AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent(); if (fromEnhancer != null) { namingPolicy = fromEnhancer.getNamingPolicy(); strategy = fromEnhancer.getStrategy(); attemptLoad = fromEnhancer.getAttemptLoad(); } }}FastClass机制在讲代理对象办法执行流程前先理解一下Cglib的FastClass机制,它的原理简略来说就是为代理类和被代理类各生成一个Class,这个Class会为代理类或被代理类的办法调配一个index,在办法执行阶段,FastClass机制能够利用办法index间接定位要调用的办法进行调用,省去了反射调用,所以从调用效率上会比JDK动静代理通过反射调用高。之前生成的class文件中Subject$$EnhancerByCGLIB$$bc785f22$$FastClassByCGLIB$$c5058ad4就是代理类的FastClass,而Subject$$FastClassByCGLIB$$a84ac285就是指标类的FastClass。 public Object invokeSuper(Object obj, Object[] args) throws Throwable { try { //FastClass并不是跟代理类一块生成的,而是在第一次执行MethodProxy invoke/invokeSuper时生成的并放在了缓存中。 this.init(); MethodProxy.FastClassInfo fci = this.fastClassInfo; return fci.f2.invoke(fci.i2, obj, args); } catch (InvocationTargetException var4) { throw var4.getTargetException(); }}private static class FastClassInfo { FastClass f1;//指标类FastClass FastClass f2;//代理类FastClass int i1; //指标类办法index int i2;//代理类办法index
private FastClassInfo() {
}}/MethodProxy invoke/invokeSuper都调用了init()private void init() { if(this.fastClassInfo == null) { Object var1 = this.initLock; synchronized(this.initLock) { if(this.fastClassInfo == null) { MethodProxy.CreateInfo ci = this.createInfo; MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo(); fci.f1 = helper(ci, ci.c1);//如果缓存中就取出,没有就生成新的FastClass fci.f2 = helper(ci, ci.c2); fci.i1 = fci.f1.getIndex(this.sig1);//获取办法的index fci.i2 = fci.f2.getIndex(this.sig2); this.fastClassInfo = fci; this.createInfo = null; } } }}代理对象办法执行流程剖析调用代理对象sayHello办法 → 调用对应的办法拦截器(LogInterceptor) → methodProxy.invokeSuper → 进入代理类CGLIB$sayHello$0办法 → 指标类sayHello办法
public class Subject$$EnhancerByCGLIB$$bc785f22 extends Subject implements Factory {
private MethodInterceptor CGLIB$CALLBACK_0; //拦截器private static final Method CGLIB$sayHello$0$Method; //被代理办法private static final MethodProxy CGLIB$sayHello$0$Proxy; //代理办法 static void CGLIB$STATICHOOK1() { // 加载生成的代理类Class对象 Class var0 = Class.forName("com.example.demo.proxy.cglib.Subject$$EnhancerByCGLIB$$bc785f22"); // 指标类Class对象 Class var1; // 通过反射获取被代理办法sayHello
CGLIB$sayHello$0$Method = ReflectUtils.findMethods(new String[]{"sayHello", "()V"}, (var1 = Class.forName("com.example.demo.proxy.cglib.Subject")).getDeclaredMethods())[0];
// 创立MethodProxy CGLIB$sayHello$0$Proxy = MethodProxy.create(var1, var0, "()V", "sayHello", "CGLIB$sayHello$0");}// 在拦截器中调用methodProxy.invokeSuper会进入这里final void CGLIB$sayHello$0() { super.sayHello();}public final void sayHello() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } // 判断拦截器是否为空,不为空调用拦截器intercept办法
if (var10000 != null) {
// @param this 代理对象自身 // @param CGLIB$sayHello$0$Method Subject类sayHello办法Method对象【动态代码块已赋值】 // @param CGLIB$emptyArgs Subject类sayHello办法参数 // @param CGLIB$sayHello$0$Proxy Subject类sayHello办法的代理办法对象【动态代码块已赋值, 即CGLIB$sayHello$0办法】
var10000.intercept(this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
} else { super.sayHello(); }}
// ...省略
}
接下来,在LogInterceptor的intercept办法中调用的MethodProxy#invokeSuper时,最终就会执行父类Subject#sayHello办法。MethodProxy#invokeSuper的执行逻辑如下 public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try { //FastClass对象并不是跟代理类对象一块生成的,而是在第一次执行MethodProxy invoke/invokeSuper时生成的并放在了缓存中。 init(); FastClassInfo fci = fastClassInfo; // 执行代理类对象CGLIB$sayHello$0办法 return fci.f2.invoke(fci.i2, obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); }}
private void init()
{ if (fastClassInfo == null) { synchronized (initLock) { if (fastClassInfo == null) { // 获取代理类的创立信息【下面有提过】 CreateInfo ci = createInfo; // 新建FastClassInfo对象 FastClassInfo fci = new FastClassInfo(); // 生成指标类对应FastClass对象 fci.f1 = helper(ci, ci.c1); // 生成代理类对应FastClass对象 fci.f2 = helper(ci, ci.c2); // 依据办法签名,获取指标类中对应sayHello办法在f1中的索引 fci.i1 = fci.f1.getIndex(sig1); // 依据办法签名,获取代理类中对应CGLIB$sayHello$0办法在f2中的索引 fci.i2 = fci.f2.getIndex(sig2); fastClassInfo = fci; createInfo = null; } } }}
/*
- FastClassInfo也是MethodProxy的一个外部类
*/
private static class FastClassInfo {
FastClass f1;//指标类FastClassFastClass f2;//代理类FastClassint i1; //指标类sayHello办法indexint i2;//代理类CGLIB$sayHello$0办法indexprivate FastClassInfo() {}
}二、Spring AOPAOP(Aspect Orient Programming),个别称为面向切面编程,作为面向对象的一种补充,用于解决零碎中散布于各个模块的横切关注点,比方事务管理、日志、缓存等等。SpringAOP则是Spring提供的一个规范易用的aop框架,依靠Spring的IOC容器,提供了极强的AOP扩大加强能力,SpringAOP的实现依附其底层采纳的JDK/CGLIB动静代理。2.1 AOP外围概念术语含意Aspect申明切面,相似于类定义,每个Aspect能够蕴含多个PointCut和AdvicePointCut切点,用来筛选须要在哪些地位做加强解决Joinpoint连接点,通过PointCut筛选进去执行加强的节点,如办法被调用时、异样抛出时等Advice连接点处执行的加强逻辑Target Object指标对象,被织入Advice的对象Weaving将Advice织入到连接点的处理过程,织入可在编译时实现(例如应用AspectJ编译器),而Spring AOP在运行时实现织入解决为了标准化AOP,Spring引入了一套AOP顶级API(AOP联盟),用来定义和应用AOP。spring-aop jar包中有个目录org.aopalliance,其中存在几个接口是AOP联盟提供的规范AOP的API
2.2 SpringAOP与AOP联盟关系
2.3 SpringAOP的实现思路在讲Spring AOP外围组件概念前,咱们首先通过一个例子直观上了解Spring AOP外围组件作用原理。应用Spring AOP的关键在于配置获取Advisor,在Spring 2.0 版本之前定义Advisor是通过实现Advisor接口(或者IntroductionAdvisor),定义拦截器和拦挡规定(切点)。应用SpringAOP大体流程为以下3点:配置获取Advisor :定义拦截器(Advice)+ 拦挡规定(切点),生成Advisor生成代理:依据Advisor生成代理对象,会生成JdkDynamicAopProxy或CglibAopProxy办法执行:执行代理办法时从Advisor取出Advice转换为MethodInvocation(连接点),执行拦截器调用//定义一个Service及实现
public interface DemoService {
}
public class DemoServiceImpl implements DemoService {
@Override
public void echo() {
System.out.println("Echo method invoke...");
}
}
//自定义PointCut,用于筛选DemoService 的echo办法
public class DemoPointCut implements Pointcut {
@Overridepublic ClassFilter getClassFilter() { return new ClassFilter() { @Override public boolean matches(Class<?> clazz) { return DemoService.class.isAssignableFrom(clazz); } };}@Overridepublic MethodMatcher getMethodMatcher() { return new MethodMatcher() { @Override public boolean matches(Method method, Class<?> targetClass) { return "echo".equals(method.getName()); } @Override public boolean isRuntime() { return false; } @Override public boolean matches(Method method, Class<?> targetClass, Object... args) { return false; } };}
}
// 实现Advice接口减少横切逻辑
public class LogInterceptor implements MethodInterceptor {
@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("Before method invoke ..."); return invocation.proceed();}
}
// 自定义Advisor
public class DemoAdvisor implements PointcutAdvisor {
@Overridepublic Advice getAdvice() { return new LogInterceptor ();}@Overridepublic Pointcut getPointcut() { return new DemoPointCut();}@Overridepublic boolean isPerInstance() { return false;}
}
// 测试方法
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory(new DemoService());proxyFactory.addAdvisor(new DemoAdvisor());// 生成代理对象DemoService proxy = (DemoService)proxyFactory.getProxy();proxy.echo();
}
//控制台输入:
Before method invoke ...
Echo method invoke...
下面的例子是通过自定义实现API的模式来配置创立Advisor,当然咱们也能够借助Spring AOP的内置实现,并把对象交由Spring来治理,让Spring容器帮咱们主动生成代理对象,Spring AOP提供了很多类来帮忙实现主动创立代理对象,它们有一个独特的父类AbstractAutoProxyCreator,AbstractAutoProxyCreator具体的创立过程前面再剖析。这里咱们应用DefaultAdvisorAutoProxyCreator演示, 下面的Demo能够改为如下模式,变动根本不大public class AutoProxyConfig {
@Beanpublic DemoService echoService() { return new DemoServiceImpl();}@Beanpublic LogInterceptor logInterceptor() { return new LogInterceptor();}@Beanpublic Advisor advisor() { NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(); advisor.setMappedName("echo"); advisor.setAdvice(logInterceptor()); return advisor;}@Beanpublic DefaultAdvisorAutoProxyCreator autoProxyCreator() { return new DefaultAdvisorAutoProxyCreator();}
}
测试方法:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AutoProxyConfig.class);// 获取代理对象DemoService demoService = context.getBean(DemoService.class);demoService.echo();
}
控制台输入:
Before method invoke ...
Echo method invoke...当Spring 2.0公布当前,Spring AOP集成了AspectJ减少了新的应用形式,即通过AspectJ注解形式(如@Aspect和@Around)定义Aspect和Adivce, 然而Spring AOP只是引入了其注解性能(提供注解驱动的AOP),底层的实现和织入形式还是1.x原先的实现体系。下面的Demo能够改为如下模式,这也是当初咱们应用AOP最罕用的模式@Aspect
@Component
public class LogAspect {
@Pointcut(value = "execution(* com.example.demo.service..*.*(..))")public void pointCut() {} @Before("pointCut()")public void logStart(JoinPoint joinPoint){ System.out.println("Before method invoke ...");}
}2.4 外围组件概念2.4.1 Advice告诉(增强器)顶级接口,通过PointCut筛选出Jointpoint时,咱们就须要在这些Jointpoint上减少横切逻辑,这些横切逻辑被称为Advice。Advice次要分成两类一般Advice与Interceptor/MethodInterceptor,无论通过aop命名空间/AspectJ注解正文的办法, 其最终都将解析成对应的Advice,所有的Advice会在最终代理办法执行阶段转换适配成MethodInterceptor被执行
应用AspectJ注解定义切面时罕用到的五个注解,每个注解会别离被包装为以下Advice, 它们实际上是对以上Advice的实现
2.4.2 InterceptorInterceptor是继承自Advice的两头接口,它示意以拦截器形式实现加强成果,Interceptor得子接口有两个:MethodInterceptor和ConstructorInterceptor,然而Spring没有提供ConstructorInterceptor的实现类,而MethodInterceptor则示意通过拦挡办法的执行来实现加强成果,上述基于AspectJ注解对应的五个Advice,实质上都是实现了MethodInterceptor(或者在执行阶段被转换为MethodInterceptor),比方实现盘绕告诉Advice类(AspectJAroundAdvice)就实现了MethodInterceptor
前置告诉AspectJMethodBeforeAdvice没有实现MethodInterceptor,然而会在执行阶段被包装为MethodBeforeAdviceInterceptor,执行包装的是MethodBeforeAdviceAdapter
2.4.3 Jointpoint通过Pointcut筛选出须要加强解决的中央就是Jointpoint。 在办法执行阶段能够通过Joinpoint实现类中获取增强器等信息,比方应用Cglib生成代理对象,在代理办法执行时就是通过CglibMethodInvocation(Joinpoint实现)取得拦截器(MethodInterceptor)并链式执行。在AOP理念中很多中央能够减少横切逻辑,如办法执行,字段设置等。Spring目前只反对办法执行这一种Joinpoint,Spring提供的Joinpoint实现如下
public interface Joinpoint {
// 执行此拦挡点,并进入到下一个连接点Object proceed() throws Throwable;// 返回保留以后连接点动态局部,这里个别指target对象Object getThis();// 返回此动态连接点 个别就为以后的MethodAccessibleObject getStaticPart();
}
public interface Invocation extends Joinpoint {
// 返回办法参数Object[] getArguments();
public interface MethodInvocation extends Invocation {
// 返回以后Method对象,成果同父类的getStaticPart办法Method getMethod();
}SpringAOP在AOP Alliance根底上减少了几个类,丰盛了AOP定义及应用概念,包含Advisor:蕴含Advice和PointCut,Spring外部应用AOP的顶级接口Pointcut: 匹配哪些类哪些办法须要被切面解决,蕴含一个ClassFilter和一个MethodMatcherClassFilter:类过滤器,定义类过滤规定,用于筛选哪些类对象须要应用AOPMethodMatcher:办法匹配器,定义方法匹配规定,用于筛选哪些办法须要应用AOP2.4.4 Advisor在AOP设计理念中通过Aspect来申明切面,每个Aspect能够蕴含多个Pointcut和Advice。在Spring AOP中,Aspect对应的实现为Advisor。Advisor是Pointcut和Advice的容器,然而一个Advisor只能蕴含一个Pointcut和Advice。配置定义Advisor是应用Spring AOP的要害。public interface Advisor {
// Spring5当前才有的空告诉,个别当作默认值Advice EMPTY_ADVICE = new Advice() {};// 该Advisor 持有的告诉器
Advice getAdvice();
boolean isPerInstance();
}
Advisor是顶级接口,然而没有给出过滤匹配切点的形式,两个次要的扩大接口IntroductionAdvisor(引介加强)和PointcutAdvisor,区别在IntroductionAdviso只能利用于类级别的拦挡,只能应用Introduction型的Advice,而PointcutAdvisor定义了class类型+办法匹配过滤形式,能够应用任何类型的Pointcut以及简直任何类型的Advice,PointcutAdvisor性能更弱小,IntroductionAdvisor平时较少用到,这里不做介绍,Spring提供的PointcutAdvisor实现十分多,这里列举其中局部实现:PointcutAdvisor应用场景AspectJPointcutAdvisorSpring解析aop命名空间时生成的Advisor,对应的Advice是AspectJMethodBeforeAdvice、AspectJAfterAdvice,、AspectJAfterReturningAdvice,、AspectJAfterThrowingAdvice和AspectJAroundAdvice,Pointcut则是AspectJExpressionPointcut,对于这个类的解析是在 ConfigBeanDefinitionParserInstantiationModelAwarePointcutAdvisorImplSpring解析被@AspectJ正文的类时生成的Advisor,这个Advisor中的 Pointcut与Advice都是由ReflectiveAspectJAdvisorFactory来解析生成的(与之对应的Advice和Pointcut同AspectJPointcutAdvisor),具备提早初始化策略DefaultPointcutAdvisor Spring提供的通用的,也被认为是最弱小的Advisor。它能够组合任意的两个Advice和PointcutBeanFactoryCacheOperationSourceAdvisorSpring缓存注解@Cacheable相干AsyncAnnotationAdvisorSpring异步办法调用注解@Async相干NameMatchMethodPointcutAdvisor基于办法名是否匹配来执行Advice,其中的Pointcut 默认是NameMatchMethodPointcutRegexpMethodPointcutAdvisor基于正则表达式来匹配执行Advice,其中的Pointcut 默认是JdkRegexpMethodPointcutBeanFactoryTransactionAttributeSourceAdvisor在注解式事务编程时, 次要是由BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource和TransactionInterceptor组合起来进行事务的操作2.4.5 PointCut定义切面的匹配点,简略的说就是去切哪些类、哪些办法,在Spring Aop中匹配的点次要是class与method,对应于为ClassFilter与MethodFilterpublic interface Pointcut {
// 类过滤器, 能够晓得哪些类须要拦挡
ClassFilter getClassFilter(); // 办法匹配器, 能够晓得哪些办法须要拦挡 MethodMatcher getMethodMatcher(); // 匹配所有对象的 Pointcut
Pointcut TRUE = TruePointcut.INSTANCE;
}Spring提供的局部PointCut实现列举:NameMatchMethodPointcut:基于办法名进行匹配。 (其中ClassFilter = ClassFilter.TRUE)ComposablePointcut:组合模式的 Pointcut, 次要分成两种: 1.组合中所有都匹配算胜利 2. 组合中都不匹配才算胜利JdkRegexpMethodPointcut:通过正则表达式来匹配办法(ClassFilter = ClassFilter.TRUE)AspectJExpressionPointcut:通过 AspectJ 包中的组件进行办法的匹配(切点表达式)TransactionAttributeSourcePointcut:Spring注解式事务的Pointcut。通过匹配办法上@Transactional标签来确定办法是否匹配2.6 Spring AOP主动动静代理应用Aspectj 提供的注解定义切面,Spring只是引入了其注解形底层的实现和织入形式还是1.x原先的实现体系,由Spring解析配置生成Advisor,这里以在SpringBoot工程应用AOP为例阐明Spring是如何主动解析配置Advisor并生成代理对象的。这也是目前咱们应用AOP的罕用形式,以日志切面为例,定义Aspect如下整体解决流程如下1.@EnableAspectJAutoProxy注解会开启AOP性能,并在我的项目启动时往IOC容器中注册组件 AnnotationAwareAspectJAutoProxyCreator,它实现了BeanPostProcessor2. AnnotationAwareAspectJAutoProxyCreator会拦挡Bean的创立过程, 判断Bean是否须要加强,如须要就会配置包装增强器(Advisor),并借助动静代理将加强逻辑织入创立的代理对象3. 办法执行阶段,对办法调用会被代理对象拦截器拦挡(以Cglib为例),执行者是CglibAopProxy.DynamicAdvisedInterceptor#intercept办法,在该办法中会通过代理对象中保留的增强器,指标对象等信息生成指标办法的拦截器链(行将增强器包装成拦截器MethodInterceptor),利用拦截器的链式机制,顺次进入每一个拦截器进行执行,AnnotationAwareAspectJAutoProxyCreator类关系图
SpringBoot 启动时refresh办法中调用this.registerBeanPostProcessors(beanFactory) 实例化和注册实现了后置处理器(BeanPostProcessor)的Bean,在初始化AnnotationAwareAspectJAutoProxyCreator时会调用BeanFactoryAware接口办法setBeanFactory将BeanFactory注入组件,同时初始化AspectJAdvisorFactory和BeanFactoryAspectJAdvisorsBuilderAdapter,BeanFactoryAspectJAdvisorsBuilderAdapter封装了工厂类AspectJAdvisorFactory,其外围的逻辑在其办法buildAspectJAdvisors中,该办法查找容器中所有@AspectJ注解的Bean,而后将其中每个advice办法包装成Advisor@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException( "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}Spring Bean创立都会进入BeanPostProcessor的处理过程,Spring AOP主动配置Advisor并通过动静代理创立Proxy对象织入加强逻辑入口也正是在AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization办法,整体流程图
代码解决入口在AbstractAutoProxyCreator#postProcessAfterInitialization办法 @Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 依据须要包装Bean return wrapIfNecessary(bean, beanName, cacheKey); } } return bean;}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // TargetSource是对被代理对象target的封装,代理对象从TargetSource获取target
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean; } // 如果曾经被加强解决过,间接返回 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 判断bean的类型是否为根底类:Advice,Pointcut,Advisor,AopInfrastructureBean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 获取办法拦截器(Advisor汇合),如果Advisor不为空则创立代理对象 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; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean;}获取 Advisor汇合办法入口(AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean) protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray();}protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 步骤1. 用于获取所有的Advisor, 包含间接配置得Advisor和用AspectJ定义的Advisor,即把AspectJ定义的bean转化为Advisor List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 步骤2. 遍历获取到的Advisor,逐个从Advisor拿到PointCut, 通过PointCut判断Advisor是否实用于以后Bean
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 拓展Advisor extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { // 对Advisor排序 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors;}// 步骤1处会进入AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisorsprotected List<Advisor> findCandidateAdvisors() { // 获取间接配置的Advisor,实现Advisor接口的bean组件 List<Advisor> advisors = super.findCandidateAdvisors(); // 获取标注@Aspect组件的bean ,并解析bean标注了@Before, @After, @AfterReturning, @AfterThrowing的办法转换为Advisor if (this.aspectJAdvisorsBuilder != null) { // aspectJAdvisorsBuilder在注册AnnotationAwareAspectJAutoProxyCreator组件时生成, // 它会在BeanFactory中查找带有@Aspect注解的Bean, 并通过AspectJAdvisorFactory为每一个Advice办法生成一个Advisor advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors;}// 步骤2处findAdvisorsThatCanApply办法最终进入以下办法判断public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { // PointCut中类过滤器是否匹配指标类 if (!pc.getClassFilter().matches(targetClass)) { return false; } // 省略 ... // 创立办法匹配器 IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); // 遍历办法对象 for (Method method : methods) { if (introductionAwareMethodMatcher != null ? // 存在某一办法匹配,则返回true introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true; } } } return false;}在讲代理创立前,先理解一下ProxyFactory,后面的例子中能够看到创立代理对象走的是ProxyFactory.getProxy(getProxyClassLoader()), 但真正创立代理对象是通过AopProxyFactory。ProxyFactory继承自ProxyCreatorSupport和AdvisedSupport,ProxyCreatorSupport默认构造函数初始化了一个默认的 AopProxyFactory(即DefaultAopProxyFactory,Spring惟一实现),AdvisedSupport用于保留Advisor、指标对象和接口等属性,ProxyFactory#getProxy办法实际上是调用了DefaultAopProxyFactory#createAopProxy(AdvisedSupport config)
Spring Aop创立代理对象并织入切面逻辑的入口AbstractAutoProxyCreator#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对象 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); // 提供的hook办法,供子类实现对代理工厂的定制 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 生成代理类 return proxyFactory.getProxy(getProxyClassLoader());}
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) { activate();}// 从父类ProxyCreatorSupport拿到代理类工厂DefaultAopProxyFactory,并将本身( ProxyFactory继承AdvisedSupport)作为参数传入,作为创立的代理对象属性// AdvisedSupport会作为后续办法执行时获取Advisor,指标对象和接口等结构拦截器链的起源
return getAopProxyFactory().createAopProxy(this);
}Spring AOP生成代理对象用了工厂模式
AopProxyFactory创立代理对象 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 判断以后类是否须要进行运行时优化,或者是指定了应用Cglib代理的形式,再或者是指标类没有用户提供的相干接口,则应用Cglib代理if (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代理生成的类,此时还是应用Jdk代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 返回Cglib代理生成对象 return new ObjenesisCglibAopProxy(config);} else { // 返回JDK代理生成对象 return new JdkDynamicAopProxy(config);}
}以下次要剖析应用Cglib形式生成代理实现代理逻辑的织入public Object getProxy(@Nullable ClassLoader classLoader) {
try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); // 判断以后类是否是曾经通过Cglib代理生成的类,如果是的,则获取其原始父类, // 并将其接口设置到须要代理的接口中 Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { // 获取父类 proxySuperClass = rootClass.getSuperclass(); // 获取父类实现的接口,并将其设置到须要代理的接口中 Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // 对指标类进行查看,次要检查点有三个: // 1. 指标办法不能应用final润饰; // 2. 指标办法不能是private类型的; // 3. 指标办法不能是包拜访权限的; // 这三个点满足任何一个,以后办法就不能被代理,此时该办法就会被略过 validateClassIfNecessary(proxySuperClass, classLoader); // 创立Enhancer对象,并且设置ClassLoader Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); // 这里AopProxyUtils.completeProxiedInterfaces()办法的次要目标是为要生成的代理类减少SpringProxy,Advised这两个须要实现的接口。这里两个接口的作用如下: // 1. SpringProxy:是一个空接口,用于标记以后生成的代理类是Spring生成的代理类; // 2. Advised:Spring生成代理类所应用的属性都保留在该接口中,包含Advisor,指标对象等属性; enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); // 获取代理类中各个办法将要应用的Interceptor(这里的Interceptor与aopaliance中的Interceptor不是同一接口), 其中就包含(DynamicAdvisedInterceptor)
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // 设置拦截器过滤器,用于筛选各个办法将要应用的Interceptor,这里的ProxyCallbackFilter.accept()办法返回的整型值正好一一对应下面Callback数组中各个拦截器的下标 enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // 生成代理对象 return createProxyClassAndInstance(enhancer, callbacks);} catch (CodeGenerationException | IllegalArgumentException ex) { // 省略} catch (Throwable ex) { throw new AopConfigException("Unexpected AOP exception", ex);}
}指标办法的执行代理对象创立好后,其实最终的拦挡工作都是交给了MethodInvocation,JDK交给ReflectiveMethodInvocation,Cglib交给CglibMethodInvocation(继承自ReflectiveMethodInvocation),执行过程图示
这里以Cglib阐明执行的大体过程:对指标办法调用实际上会进入代理对象办法的执行,如后面Cglib动静代理局部剖析,通过Cglib生成代理对象的办法执行最终会进入CglibAopProxy.DynamicAdvisedInterceptor#intercept办法在DynamicAdvisedInterceptor#intercept办法中通过代理对象持有的ProxyFactory(继承自AdvisedSupport)将代理对象保留的Advisor转化为拦截器链同时结构CglibMethodInvocation作为拦截器链调用入口,CglibMethodInvocation继承自ReflectiveMethodInvocation,入口办法proceed实际上会进入ReflectiveMethodInvocation#proceed办法在ReflectiveMethodInvocation#proceed中获取每一个办法拦截器并执行其invoke办法(若以后拦截器不是最初一个),每一个拦截器会期待下一个拦截器执行实现返回当前再继续执行,在拦截器执行invoke办法前后执行加强解决;如果为最初一个拦截器则调用指标办法拦截器链的机制,保障加强解决办法与指标办法的执行程序
链式调用机制
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } @Override @Nullable 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 { if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // 拿到指标对象 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // 将代理对象保留的Advisor转化为拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; //没有增强器,同时该办法是public得 就间接调用指标办法(不拦挡) if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { // 结构CglibMethodInvocation作为拦截器链调用入口并执行调用 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); } } }}