spring AOP

AOP概念java

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


AOP做用spring

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


AOP术语 ide

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

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

加强定义了切面是什么及什么时候使用。是什么,是一段代码;什么时候使用,能够是某个方法调用前、调用后、抛出异常后。spa

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

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

织入——在目标对象的生命周期里有多个点能够进行织入:
一、编译期,切面在目标类编译时被织入,须要特殊的Java编译器。
二、类加载期,切面在目标类加载到JVM时被织入,须要特殊的类装载器。
三、运行期,即动态代理织入,在运行期为目标类添加加强生成子类。
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种类型的切点
// 一、静态方法切点,抽象类,默认匹配全部的类,有两个实现类
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。

一、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

 二、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
相关文章
相关标签/搜索