AOP全称是Aspect-Oriented Programming,对应到编程术语中就是面向切面的编程。简单来讲就是执行一段代码以前以及以后分别插入另外一段代码,从而实现对这段代码全方位监视。java
链接点,抽象统一了method,constructor,field。好比最经常使用的Method,对应到类就是`ReflectiveMethodInvocation`,能够拦截方法调用,并添加自定义的advice。这个概念是aop内部封装的过程当中用到,使用者不须要直接接触。spring
切入点,其实就是一个过滤器,其子类衍生出静态的切入点,动态切入点,基于表达式的切入点等。本质就是经过对类,方法,输入参数的解析,判断哪些是须要进行拦截的,哪些是能够被过滤的。编程
通知,或者加强,这两种翻译均可以强行解释,是为了实现拦截Jointpoint后具体的逻辑,好比常见的MethodInterceptor,对方法进行拦截。这个接口是使用者最关心的,直接关系到业务逻辑。缓存
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency>
spring支持两种动态代理方案,1种是基于jdk的动态代理,第2种是基于cglib的动态代理。详细参考`DefaultAopProxyFactory`,spring基于3个条件来选择哪种动态代理方案,只要符合其中一个条件spring就会采用基于cglib的方案。1.是否须要优化(基于cglib的动态代理方案执行性能比JDK的高);2.是否声明了代理对象是类(JDK不支持对类的动态代理,而cglib支持);3.没有代理接口声明;全部配置能够经过`org.springframework.aop.framework.ProxyFactory`配置。用户注册的adivce先被缓存在列表中(Interceptor是Advice接口的子接口),若是没有显示声明则会被封装成`DefaultPointcutAdvisor`,这里就涉及到Pointcut这个术语,默认的Pointcut容许拦截全部类和方法。ide
核心类是`JDKDynamicAopProxy`,首先根据配置选择型的将spring本身的3个接口加入到代理接口,而后本身实现了JDK中的`InvocationHandler`接口。当JDK的动态代理回调`InvocationHandler`的时候,先判断是不是spring本身增长的几个接口,若是是则经过反射调用直接返回,若是不是则经过执行`JoinPoint`的子类`ReflectiveMethodInvocation`,回调第一个advice,以后的advice经过使用者本身触发调用,这样造成了一个调用链。须要注意的是,spring为了提升效率,额外拦截了hashcode和equals方法直接处理,也不会进入advice的拦截处理流程。假如咱们有两个advice,那么实际的执行顺序为性能
advice1.before -> advice2.before -> poxy.process-> advice2.after -> advice1.after
详细demo参考优化
public class AopTest { public static void main(String[] args){ System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); test(); } public static void test(){ // 基于对类的代理 ProxyFactory proxyFactory = new ProxyFactory(); // target 表示被真正执行代理的实例 proxyFactory.setTarget(new AopTester()); proxyFactory.setInterfaces(AopInterface.class); // advice 能够对调用进行拦截从而实现aop proxyFactory.addAdvice(new MyInterceptor1()); proxyFactory.addAdvice(new MyInterceptor1()); AopInterface aopTester = (AopInterface) proxyFactory.getProxy(); System.out.println(aopTester.run("test")); } /** * 被代理的接口 */ public static interface AopInterface{ public String run(String s); } /** * 被代理的类 */ public static class AopTester implements AopInterface{ @Override public String run(String s){ return s+" ing ..."; } } /** * 拦截器1,也是advice,提供通知 */ public static class MyInterceptor1 implements MethodInterceptor{ @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("1 before"); Object obj = invocation.proceed(); System.out.println(obj); System.out.println("1 after"); return "1 "+obj; } } /** * 拦截器2,也是advice,提供通知 */ public static class MyInterceptor2 implements MethodInterceptor{ @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("2 before"); Object obj = invocation.proceed(); System.out.println(obj); System.out.println("2 after"); return "2 "+obj; } } }
spring的aop以动态代理为技术基础,结合JDK和cglib的proxy方案,抽象出Pointcut和Advice两个核心接口,让使用者很是方便的控制须要拦截的内容以及拦截后的逻辑。spa
版本 4.3.10.RELEASE翻译