zoukankan      html  css  js  c++  java
  • spring AOP

    AOP概念

     AOP即面向切面编程,指把不应该放在业务逻辑里的横切关注点抽取出来封装到切面类的方法里,当程序运行时再把这些横切关注点织入到一个或多个连接点。


    AOP作用

    业务逻辑并不知道切面的存在,也不必不用去关心切面,实现了业务逻辑和横切关注点的分离


    AOP术语 

    横切关注点是散布应用多处的功能;横切关注点在概念上应该与业务逻辑分离,但往往会直接嵌入到应用的业务逻辑中。

    切面是抽取横切关注点并封装而形成的类。

    增强定义了切面是什么及何时使用。是什么,是一段代码;何时使用,可以是某个方法调用前、调用后、抛出异常后。

    切点定义了哪些方法调用增强,切点只定义到某个方法上。

    连接点由增强和切点共同定义,是使用增强的时机,即某个目标对象的某个方法调用之后、之前或抛出异常后插入增强的这个时间点;spring仅支持方法上的连接点。其它的AOP实现还支持其它的连接点,比如:类初始化前、类初始化后。

    织入——在目标对象的生命周期里有多个点可以进行织入:
    1、编译期,切面在目标类编译时被织入,需要特殊的Java编译器。
    2、类加载期,切面在目标类加载到JVM时被织入,需要特殊的类装载器。
    3、运行期,即动态代理织入,在运行期为目标类添加增强生成子类。
    spring采用动态代理织入,AspectJ采用编译期织入或类加载期织入。

    引入允许我们向现有的类添加新方法或属性。

    代理,一个类被AOP织入增强后,就产生了一个结果类,它是融合了原类和增强逻辑的代理类。


    spring AOP

    Spring AOP使用动态代理在运行期把增强逻辑织入到目标对象。Spring AOP使用了两种动态代理机制,一种是基于JDK的动态代理;一种是基于CGlib的动态代理。

    package org.springframework.aop.framework;
    public interface AopProxy {
        Object getProxy();
    
        Object getProxy(ClassLoader var1);
    }
    View Code
    class CglibAopProxy implements AopProxy{}
    View Code
    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler{}
    View Code

    spring 增强

    AOP联盟的目的是定义标准的AOP规范,以便各种遵守标准的具体实现可以相互调用

    // 增强
    public interface Advice {
    }
    public interface Interceptor extends Advice {
    }
    // 环绕增强
    public interface MethodInterceptor extends Interceptor {
    }
    AOP联盟接口
    // 前置增强
    public interface BeforeAdvice extends org.aopalliance.aop.Advice {
    }
    // spring只支持方法上的连接点,所以只有一个子接口MethodBeforeAdvice
    public interface MethodBeforeAdvice extends BeforeAdvice {
    }
    
    // 后置增强,有两个子接口,AfterReturningAdvice和ThrowsAdvice
    public interface AfterAdvice extends org.aopalliance.aop.Advice {
    }
    public interface AfterReturningAdvice extends AfterAdvice {
    }
    public interface ThrowsAdvice extends AfterAdvice {
    }
    
    // 环绕增强,直接使用AOP联盟定义的接口
    public interface MethodInterceptor extends Interceptor {
    }
    
    // 引入增强
    public interface DynamicIntroductionAdvice extends org.aopalliance.aop.Advice {
    }
    public interface IntroductionInterceptor 
    extends org.aopalliance.intercept.MethodInterceptor, org.springframework.aop.DynamicIntroductionAdvice {
    }
    // 引入增强的实现类
    public class DelegatingIntroductionInterceptor extends IntroductionInfoSupport implements IntroductionInterceptor {
    // 引入增强可以为目标类创建实现某接口的代理类,为目标类添加方法和成员变量;
    // 引入增强的连接点是类级别的,不是方法级别的。
    }
    spring接口 

    demo1——前置增强

    package com.test.spring;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.ProxyFactory;
    
    import java.lang.reflect.Method;
    
    /**
     * 也可以通过IOC配置spring的代理工厂
     */
    public class Driver {
        public static void main(String[] args) {
            // 目标对象
            Tank tank = new Tank();
            // 切面类
            LogBeforeAdvice beforeAdvice = new LogBeforeAdvice();
            //  spring代理工厂
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(tank);
            proxyFactory.addAdvice(beforeAdvice);
            // 获取代理对象
            Tank proxy = (Tank) proxyFactory.getProxy();
            proxy.run();
        }
    }
    class Tank {
        public void run() {
            System.out.println("run ...");
        }
    }
    class LogBeforeAdvice implements MethodBeforeAdvice {
        @Override
        // method是目标类的方法;args是目标类方法参数;obj是目标类实例
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("begin ...");
        }
    }
    View Code
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
    pom.xml

    demo2——引入增强

    package com.test.spring;
    
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.aop.support.DelegatingIntroductionInterceptor;
    
    public interface Monitorable {
        void setMonitorActive(boolean active);
    }
    class MyDelegatingIntroductionInterceptor extends DelegatingIntroductionInterceptor implements Monitorable {
        private boolean monitorActive;
        @Override
        public void setMonitorActive(boolean active) {
            this.monitorActive = active;
        }
        public Object invoke(MethodInvocation mi) throws Throwable {
           Object obj = null;
           if (monitorActive) {
               System.out.println("begin ...");
               obj = super.invoke(mi);
           } else {
               obj = super.invoke(mi);
           }
           return null;
        }
    
    }
    class Tank {
        public void run() {
            System.out.println("run ...");
        }
    }
    class Driver {
        public static void main(String[] args) {
            // 引入增强
            MyDelegatingIntroductionInterceptor interceptor = new MyDelegatingIntroductionInterceptor();
            //  spring代理工厂
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(new Tank());
            proxyFactory.addAdvice(interceptor);
            // 由于引入增强一定通过CGLib生成子类,所以必须强制设置为true,否则报错
            proxyFactory.setProxyTargetClass(true);
            // 获取代理对象
            Monitorable proxy = (Monitorable) proxyFactory.getProxy();
            Tank tank = (Tank) proxy;
            proxy.setMonitorActive(true);
            tank.run();
    
        }
    }
    View Code
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
    pom.xml

    spring 切点和切面 

    由于增强既包含横切代码,又包含连接点信息,如方法执行前、执行后,所以可以仅通过增强类生成一个切面,如上面前置增强、引入增强的例子。但有一个问题,增强被织入到目标类的所有方法中了,这时需要使用切点。

    切点仅代表目标类连接点的部分信息,即类和方法的定位,所以仅有切点无法生成一个切面,必须结合增强才能生成切面。spring通过Pointcut接口描述切点,通过Advisor接口描述切面,切面包含增强和连接点信息。


    spring切点

    package org.springframework.aop;
    
    public interface Pointcut {
        Pointcut TRUE = TruePointcut.INSTANCE;
    
        ClassFilter getClassFilter();
    
        MethodMatcher getMethodMatcher();
    }
    
    public interface ClassFilter {
        ClassFilter TRUE = TrueClassFilter.INSTANCE;
        // 匹配类
        boolean matches(Class<?> var1);
    }
    
    public interface MethodMatcher {
        MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
        // 匹配方法签名
        boolean matches(Method var1, Class<?> var2);
        // 返回true,表示还要匹配入参;false,表示只匹配方法签名
        boolean isRuntime();
        // 还要检查实际的入参
        boolean matches(Method var1, Class<?> var2, Object... var3);
    }
    spring切点接口
    spring提供了6种类型的切点
    // 1、静态方法切点,抽象类,默认匹配所有的类,有两个实现类
    public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {
        private ClassFilter classFilter;
    
        public StaticMethodMatcherPointcut() {
            this.classFilter = ClassFilter.TRUE;
        }
    
        public void setClassFilter(ClassFilter classFilter) {
            this.classFilter = classFilter;
        }
    
        public ClassFilter getClassFilter() {
            return this.classFilter;
        }
    
        public final MethodMatcher getMethodMatcher() {
            return this;
        }
    }
    // 简单字符串匹配方法签名
    public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut implements Serializable {}
    // 正则匹配方法签名
    public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPointcut implements Serializable {}
    
    2、动态方法切点,抽象类,默认匹配所有类
    public abstract class DynamicMethodMatcherPointcut extends DynamicMethodMatcher implements Pointcut {
        public DynamicMethodMatcherPointcut() {
        }
    
        public ClassFilter getClassFilter() {
            return ClassFilter.TRUE;
        }
    
        public final MethodMatcher getMethodMatcher() {
            return this;
        }
    }
    
    3、注解切点
    public class AnnotationMatchingPointcut implements Pointcut {}
    
    4、表达式切点
    public interface ExpressionPointcut extends Pointcut {
    }
    spring切点实现

    spring切面 

    // 一般切面,连接点是目标类的所有方法,一般不会直接使用
    public interface Advisor {
        // spring切面组合了AOP联盟的Advice
        Advice getAdvice();
    
        boolean isPerInstance();
    }
    
    // 包含切点的切面,通过父类还包含增强
    public interface PointcutAdvisor extends Advisor {
        // 组合了切点
        Pointcut getPointcut();
    }
    
    import org.aopalliance.intercept.MethodInterceptor;
    // 引入切面
    public interface IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice {
    }
    spring切面接口

    包含切点的切面——PointcutAdvisor的实现 

    public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable {
    // 最常用的切面;一般通过扩展该类可以定义自己的切面
    }
    
    public class NameMatchMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor {
    // 按方法名定义切点
    }
    
    public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor {
    // 按正则表达式定义切点
    }
    
    public abstract class StaticMethodMatcherPointcutAdvisor extends StaticMethodMatcherPointcut implements PointcutAdvisor, Ordered, Serializable {
    // 按method对象定义切点,默认匹配所有类
    }
    
    public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor implements BeanFactoryAware {
    // 按AspectJ表达式定义切点
    }
    
    public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
    // 按AspectJ语法定义切点
    }
    spring切面实现 

    demo1——StaticMethodMatcherPointcutAdvisor

    package com.test.spring;
    
    import org.springframework.aop.ClassFilter;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
    
    import java.lang.reflect.Method;
    
    /**
     * 也可以通过IOC配置spring的代理工厂
     */
    class Driver {
        public static void main(String[] args) {
            MyAdvisor myAdvisor = new MyAdvisor(); // 切面
            LogBeforeAdvice beforeAdvice = new LogBeforeAdvice(); // 前置增强
            myAdvisor.setAdvice(beforeAdvice); // 把增强添加到切面
            //  spring代理工厂
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.addAdvisor(myAdvisor); // 传入切面
            proxyFactory.setProxyTargetClass(true); // 不使用JDK动态代理
            proxyFactory.setTarget(new Car()); // 传入目标对象
            Car proxy = (Car) proxyFactory.getProxy(); // 获取代理对象
            proxy.run();
            proxyFactory.setTarget(new Tank()); // 传入目标对象
            Tank proxy2 = (Tank) proxyFactory.getProxy(); // 获取代理对象
            proxy2.run();
        }
    }
    class Tank {
        public void run() { System.out.println("run ...");}
        public void stop() { System.out.println("stop ...");}
    }
    class Car {
        public void run() {
            System.out.println("car run ...");
        }
    }
    // 切面类
    class MyAdvisor extends StaticMethodMatcherPointcutAdvisor {
        @Override
        // 必须实现
        public boolean matches(Method method, Class<?> aClass) {
            return "run".equals(method.getName());
        }
        // 可以不实现,默认匹配所有类
        public ClassFilter getClassFilter() {
            return new ClassFilter() {
                @Override
                public boolean matches(Class<?> clazz) {
                    // 匹配Tank类及其子类
                    return Tank.class.isAssignableFrom(clazz) || Car.class.isAssignableFrom(clazz);
                }
            };
        }
    }
    // 增强类
    class LogBeforeAdvice implements MethodBeforeAdvice {
        @Override
        // method是目标类的方法;args是目标类方法参数;obj是目标类实例
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("begin ...");
        }
    }
    View Code
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
    pom.xml

    demo2——RegexpMethodPointcutAdvisor

    package com.test.spring;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
    
    import java.lang.reflect.Method;
    
    /**
     * 也可以通过IOC配置spring的代理工厂
     */
    class Driver {
        public static void main(String[] args) {
            // 这个切面类功能齐备,一般不需要扩展,直接拿来用就可以了
            RegexpMethodPointcutAdvisor myAdvisor = new RegexpMethodPointcutAdvisor();
            LogBeforeAdvice beforeAdvice = new LogBeforeAdvice(); // 前置增强
            myAdvisor.setAdvice(beforeAdvice); // 把增强添加到切面
            myAdvisor.setPattern(".*run");// 匹配的是全限定方法名,即带类名的方法名
            //  spring代理工厂
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.addAdvisor(myAdvisor); // 传入切面
            proxyFactory.setProxyTargetClass(true); // 不使用JDK动态代理
            proxyFactory.setTarget(new Car()); // 传入目标对象
            Car proxy = (Car) proxyFactory.getProxy(); // 获取代理对象
            proxy.run();
            proxyFactory.setTarget(new Tank()); // 传入目标对象
            Tank proxy2 = (Tank) proxyFactory.getProxy(); // 获取代理对象
            proxy2.run();
        }
    }
    class Tank {
        public void run() { System.out.println("run ...");}
        public void stop() { System.out.println("stop ...");}
    }
    class Car {
        public void run() {
            System.out.println("car run ...");
        }
    }
    // 增强类
    class LogBeforeAdvice implements MethodBeforeAdvice {
        @Override
        // method是目标类的方法;args是目标类方法参数;obj是目标类实例
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("begin ...");
        }
    }
    View Code
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
    pom.xml

    demo3——动态切面

    package com.test.spring;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    import org.springframework.aop.support.DynamicMethodMatcherPointcut;
    
    import java.lang.reflect.Method;
    
    /**
     * 也可以通过IOC配置spring的代理工厂
     */
    class Driver {
        public static void main(String[] args) {
            DefaultPointcutAdvisor myAdvisor = new DefaultPointcutAdvisor(); // 切面
            LogBeforeAdvice beforeAdvice = new LogBeforeAdvice(); // 前置增强
            myAdvisor.setAdvice(beforeAdvice); // 把增强添加到切面
            MyDynamicMethodMatcherPointcut myPointcut = new MyDynamicMethodMatcherPointcut(); // 切点
            myAdvisor.setPointcut(myPointcut); // 把切点添加到切面
    
            ProxyFactory proxyFactory = new ProxyFactory(); //  spring代理工厂
            proxyFactory.addAdvisor(myAdvisor); // 传入切面
            proxyFactory.setProxyTargetClass(true); // 不使用JDK动态代理
    
            proxyFactory.setTarget(new Tank()); // 传入目标对象
            Tank proxy2 = (Tank) proxyFactory.getProxy(); // 获取代理对象
            proxy2.run("tank");
            proxy2.run("tank");
            proxy2.stop("tank");
            proxy2.stop("tank");
    
            Method[] methods = new Tank().getClass().getMethods();
            for (Method method : methods) {
                System.out.println(method);
            }
        }
    }
    class Tank {
        public void run(String name) { System.out.println(name + " run ...");}
        public void stop(String name) { System.out.println(name + " stop ...");}
    }
    // 增强类
    class LogBeforeAdvice implements MethodBeforeAdvice {
        @Override
        // method是目标类的方法;args是目标类方法参数;obj是目标类实例
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("begin ...");
        }
    }
    class MyDynamicMethodMatcherPointcut extends DynamicMethodMatcherPointcut {
        /** DynamicMethodMatcherPointcut类既有静态检查的方法,也有动态检查的方法
         *  由于动态检查对性能影响很大,所以应当避免每次对目标类的各个方法进行动态检查
         *
         *  spring采用这样的机制:
         *  在创建代理时对目标类的每个方法做静态检查
         *  如果方法不匹配,则运行时不再做动态检查
         *  如果方法匹配,运行时再做动态检查
         */
        @Override
        // 唯一必须实现的方法
        public boolean matches(Method method, Class<?> aClass, Object... args) {
            System.out.println("做动态检查");
            String name = (String)args[0];
            return name.equals("tank");
        }
    //    @Override
    //    public ClassFilter getClassFilter() {
    //        return new ClassFilter() {
    //            @Override
    //            public boolean matches(Class<?> clazz) {
    //                System.out.println("调用" + clazz.getName() + ".getClassFilter方法做静态检查");
    //                return Tank.class.isAssignableFrom(clazz);
    //            }
    //        };
    //    }
    //    @Override
    //    public boolean matches(Method method, Class<?> clazz) {
    //        System.out.println("静态检查" + method.getName() + "方法");
    //        return "run".equals(method.getName());
    //    }
    }
    View Code
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
    pom.xml
    // 控制台输出分析
    // 1.在创建代理时对目标类的每个方法做静态检查
    调用com.test.spring.Tank.getClassFilter方法做静态检查
    静态检查run方法
    调用com.test.spring.Tank.getClassFilter方法做静态检查
    静态检查stop方法
    调用com.test.spring.Tank.getClassFilter方法做静态检查
    静态检查toString方法
    调用com.test.spring.Tank.getClassFilter方法做静态检查
    静态检查clone方法
    
    // 2.第一次调用方法时,调用静态检查
    调用com.test.spring.Tank.getClassFilter方法做静态检查
    静态检查run方法
    // 3.如果方法匹配,运行时再做动态检查
    做动态检查
    begin ...
    tank run ...
    // 4.第二次调用方法时,不再做静态检查
    // 5.做动态检查
    做动态检查
    begin ...
    tank run ...
    // 2.第一次调用方法时,调用静态检查
    调用com.test.spring.Tank.getClassFilter方法做静态检查
    静态检查stop方法
    // 3.如果方法不匹配,运行时不再做动态检查(这里不再做动态检查,提高了性能)
    tank stop ...
    // 4.第二次调用方法时,不再做静态检查
    tank stop ...
    
    // 如果去掉静态检查方法,如下所示,调用每个方法时都会做动态检查
    做动态检查
    begin ...
    tank run ...
    做动态检查
    begin ...
    tank run ...
    做动态检查
    begin ...
    tank stop ...
    做动态检查
    begin ...
    tank stop ...
    
    
    
    // 标类的所有方法,在创建代理时也并不是对目标类的每个方法做静态检查
    public void com.test.spring.Tank.run(java.lang.String)
    public void com.test.spring.Tank.stop(java.lang.String)
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public java.lang.String java.lang.Object.toString()
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    输出分析

    spring自动创建代理 

    在前面的示例中,需要被代理的bean都需要使用一个ProxyFactory的Bean来配置,配置烦琐;spring为此提供了自动代理机制,让容器自动生成代理,Spring使用BeanPostProcessor来完成这项工作。

    BeanPostProcessor的实现有BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator。

    1、BeanNameAutoProxyCreator的使用——为一组特定名称的bean自动创建代理实例:

    package com.test.spring;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.lang.reflect.Method;
    
    @Configuration
    class MyConfig {
        @Bean
        public Tank tank() { return new Tank();}
        @Bean
        public Car car() { return new Car();}
        @Bean
        public LogBeforeAdvice logBeforeAdvice() {return new LogBeforeAdvice();}
        @Bean
        public BeanNameAutoProxyCreator autoProxyCreator() {
            BeanNameAutoProxyCreator autoProxyCreator = new BeanNameAutoProxyCreator();
            // 为一组特定名称的bean自动创建代理实例
            autoProxyCreator.setBeanNames(new String[]{"tank", "car"});// 设置目标类
            autoProxyCreator.setInterceptorNames("logBeforeAdvice"); // 设置增强类
            autoProxyCreator.isOptimize(); // 强制使用CGLib
            return autoProxyCreator;
        }
    }
    /**
     * 也可以通过IOC配置spring的代理工厂
     */
    public class Driver {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            Tank tank = context.getBean(Tank.class);
            tank.stop();
            Car car = context.getBean(Car.class);
            car.run();
        }
    }
    class Tank {
        public void run() { System.out.println("run ...");}
        public void stop() { System.out.println("stop ...");}
    }
    class Car {
        public void run() { System.out.println("car run ...");}
    }
    // 增强类
    class LogBeforeAdvice implements MethodBeforeAdvice {
        @Override
        // method是目标类的方法;args是目标类方法参数;obj是目标类实例
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("begin ...");
        }
    }
    View Code
       <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
    pom.xml

     2、DefaultAdvisorAutoProxyCreator的使用——扫描容器中的切面Advisor,并将切面自动织入匹配的bean,并创建代理

    package com.test.spring;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.lang.reflect.Method;
    
    @Configuration
    class MyConfig {
        @Bean
        public Tank tank() { return new Tank();}
        @Bean
        public Car car() { return new Car();}
        @Bean
        public LogBeforeAdvice logBeforeAdvice() {return new LogBeforeAdvice();}
        @Bean
        public RegexpMethodPointcutAdvisor regexpMethodPointcutAdvisor(LogBeforeAdvice logBeforeAdvice) {
            RegexpMethodPointcutAdvisor myAdvisor = new RegexpMethodPointcutAdvisor();
            myAdvisor.setAdvice(logBeforeAdvice); // 把增强添加到切面
            myAdvisor.setPattern(".*run");// 匹配的是全限定方法名,即带类名的方法名
            return myAdvisor;
        }
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            return new DefaultAdvisorAutoProxyCreator();
        }
    }
    /**
     * 也可以通过IOC配置spring的代理工厂
     */
    public class Driver {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            Tank tank = context.getBean(Tank.class);
            tank.stop();
            Car car = context.getBean(Car.class);
            car.run();
        }
    }
    class Tank {
        public void run() { System.out.println("run ...");}
        public void stop() { System.out.println("stop ...");}
    }
    class Car {
        public void run() { System.out.println("car run ...");}
    }
    // 增强类
    class LogBeforeAdvice implements MethodBeforeAdvice {
        @Override
        // method是目标类的方法;args是目标类方法参数;obj是目标类实例
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("begin ...");
        }
    }
    View Code
       <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
    View Code

    spring 注解方式创建代理

    demo1——使用工厂类AspectJProxyFactory 

    package com.test.spring;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
    
    @Aspect
    // 切面类必须为public的
    public class MyAdvice {
        @Before("execution(* com.test.spring.Car.*(..))")
        public void before() {
            System.out.println("begin ...");
        }
    }
    class Car {
        public void run() { System.out.println("car run ...");}
    }
    
    class MyTest {
        public static void main(String[] args) {
            AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
            proxyFactory.setTarget(new Car());
            proxyFactory.addAspect(MyAdvice.class);
            Car proxy = (Car)proxyFactory.getProxy();
            proxy.run();
        }
    }
    View Code
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>1.7.4</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.7.4</version>
        </dependency>
    pom.xml

     demo2——使用BeanPostProcessor的实现类AnnotationAwareAspectJAutoProxyCreator自动扫描切面类,并织入到目标类

    package com.test.spring;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Aspect
    // 切面类必须为public的
    public class MyAdvice {
        @Before("execution(* com.test.spring.Car.*(..))")
        public void before() {
            System.out.println("begin ...");
        }
    }
    class Car {
        public void run() { System.out.println("car run ...");}
    }
    @Configuration
    class MyConfig {
        @Bean
        public Car car() { return new Car(); }
        @Bean
        public MyAdvice myAdvice() { return new MyAdvice(); }
        @Bean
        public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
            return new AnnotationAwareAspectJAutoProxyCreator();
        }
    }
    class MyTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            Car proxy = context.getBean(Car.class);
            proxy.run();
            context.close();
        }
    }
    View Code
     <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>1.7.4</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.7.4</version>
        </dependency>
    pom.xml

     demo3——使用注解EnableAspectJAutoProxy

    在spring内部依旧采用AnnotationAwareAspectJAutoProxyCreator自动创建代理。
    注解EnableAspectJAutoProxy有一个proxyTargetClass可以赋值为布尔值,如果为true,表示使用CGLib;默认为fasle;不过即使设置为false,如果目标类没有实现接口,自动使用CGLib。

    package com.test.spring;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    class Car {
        public void run() { System.out.println("car run ...");}
    }
    @Aspect
    class MyAdvice {
        @Before("execution(* com.test.spring.Car.*(..))")
        public void before() {
            System.out.println("begin ...");
        }
    }
    @Configuration
    @EnableAspectJAutoProxy
    class MyConfig {
        @Bean
        public Car car() {
            return new Car();
        }
        @Bean
        public MyAdvice myAdvice() {
            return new MyAdvice();
        }
    }
    class MyTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            Car car = context.getBean(Car.class);
            car.run();
            context.close();
        }
    }
    View Code
     <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>1.7.4</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.7.4</version>
        </dependency>
    View Code

    demo4——引入增强

    package com.test.spring;
    
    public interface Moveable {
        public void stop();
    }
    class Car { // Car类并没有实现Moveable接口
        public void run() {
            System.out.println("car run ...");
        }
    }
    View Code
    package com.test.spring;
    // 实现类必须是public的,否则报错
    public class MoveableImpl implements Moveable{
        @Override
        public void stop() { System.out.println("car stop ..."); }
    }
    View Code
    package com.test.spring;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @Aspect
    class MyAdvice {
        // value参数必须是类的全限定名
        @DeclareParents(value = "com.test.spring.Car", defaultImpl =MoveableImpl.class)
        public Moveable moveable;
    }
    @Configuration
    @EnableAspectJAutoProxy()
    class MyConfig {
        @Bean
        public Car car() { return new Car(); }
        @Bean
        public MyAdvice myAdvice() { return new MyAdvice(); }
    }
    class MyTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            Car car = context.getBean(Car.class);
            car.run();
            Moveable moveable = (Moveable)car;
            moveable.stop();
            context.close();
        }
    }
    View Code
       <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>1.7.4</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.7.4</version>
        </dependency>
    View Code

     

  • 相关阅读:
    同一部电脑配两个git账号
    在span中,让里面的span垂直居中用这个
    三张图搞懂JavaScript的原型对象与原型链
    vue2.0 生命周期
    js中__proto__和prototype的区别和关系?
    【转】css 包含块
    【转】BFC(block formating context)块级格式化上下文
    javascript中函数的5个高级技巧
    toString() 和 valueOf()
    桌面图标列表排列小工具
  • 原文地址:https://www.cnblogs.com/Mike_Chang/p/10246388.html
Copyright © 2011-2022 走看看