跳到主要内容

AOP详解-动态代理实现AOP

1. 什么是动态代理

  • 动态代理实际上就是 Java 中的一个方法,可以动态创建一组指定接口的实现对象(在运行时创建)
    interface A {}
    interface B {}
    //obj对象的类型实现了A和B两个接口
    Object obj = 方法(new Class[]{A.class, B.class})

2. 动态代理的使用

  • 代码:
    public static Object newProxyInstance(ClassLoader loader, 
    Class<?>[] interfaces, InvocationHandler h)
    • ClassLoader loader: 方法需要动态生成一个类,这个类实现A、B两个接口,然后创建这个类的对象。这个生成的类需要加载到方法区中,因此需要一个 ClassLoader 来加载这个类
    • Class<?>[] interfaces: 需要代理对象实现的数组
    • InvocationHandler h: 调用处理器
    public void test3() {
    // 代理对象实现的所有接口中的方法,内容都是调用InvocationHandler的invoke()方法
    ClassLoader classLoader = this.getClass().getClassLoader();
    //这里创建一个空实现的调用处理器。
    InvocationHandler invocationHandler = new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("你好!!!!");
    return "Hello";//这里改为返回"Hello"
    }
    };
    Object obj = Proxy.newProxyInstance(classLoader, new Class[]{A.class, B.class}, invocationHandler);
    //强转为A和B接口类型,说明生成的代理对象实现了A和B接口
    A a = (A) obj;
    B b = (B) obj;
    a.toString();//注意这里调用了toString()方法
    b.getClass();//注意这里调用了getClass()方法
    //这里在A接口中添加了一个方法public Object aaa(String s1, int i);
    Object hello = a.aaa("Hello", 100);
    System.out.println(obj.getClass());//这里看一下代理对象是什么
    System.out.println(hello);//这里看一下返回值是什么
    }
  • invoke 方法
    invoke方法

3. 初步实现 AOP

  • 接口

    package demo2;

    //服务生
    public interface Waiter {
    //服务方法
    public void server();
    }
  • 接口实现类

    package demo2;

    public class ManWaiter implements Waiter {

    @Override
    public void server() {
    System.out.println("服务中");
    }
    }
  • 动态代理进行增强

    package demo2;

    import org.junit.Test;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;

    public class Demo2 {
    @Test
    public void test1() {
    Waiter waiter = new ManWaiter();
    waiter.server();
    }

    @Test
    public void test2() {
    Waiter manWaiter = new ManWaiter();
    ClassLoader classLoader = this.getClass().getClassLoader();
    Class[] interfaces = {Waiter.class};
    InvocationHandler invocationHandler = new WaiterInvocationHandler(manWaiter);
    //得到代理对象,代理对象就是在目标对象的基础上进行了增强的对象
    Waiter waiter = (Waiter) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    waiter.server();//前面添加“你好”,后面添加“再见”
    }
    }

    class WaiterInvocationHandler implements InvocationHandler {

    private Waiter waiter;

    WaiterInvocationHandler(Waiter waiter) {
    this.waiter = waiter;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("你好");
    waiter.server();//调用目标对象的方法
    System.out.println("再见");
    return null;
    }
    }

4. 完善的 AOP 实现

  • 前置增强接口

    /**
    * 前置增强
    */
    public interface BeforeAdvice {
    public void before();
    }
  • 后置增强接口

    public interface AfterAdvice {
    public void after();
    }
  • 代理对象产生代码封装

    package demo3;

    import com.sun.org.apache.regexp.internal.RE;
    import org.junit.After;

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    /**
    * 1、创建代理工厂
    * 2、给工厂设置目标对象、前置增强、后置增强
    * 3、调用creatProxy()得到代理对象
    * 4、执行代理对象方法时,先执行前置增强,然后是目标方法,最后是后置增强
    */
    //其实在Spring中的AOP的动态代理实现的一个织入器也是叫做ProxyFactory
    public class ProxyFactory {
    private Object targetObject;//目标对象
    private BeforeAdvice beforeAdvice;//前值增强
    private AfterAdvice afterAdvice;//后置增强

    /**
    * 用来生成代理对象
    * @return
    */
    public Object creatProxy() {
    /**
    * 给出三个参数
    */
    ClassLoader classLoader = this.getClass().getClassLoader();
    //获取当前类型所实现的所有接口类型
    Class[] interfaces = targetObject.getClass().getInterfaces();

    InvocationHandler invocationHandler = new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    /**
    * 在调用代理对象的方法时,会执行这里的内容
    */
    if(beforeAdvice != null) {
    beforeAdvice.before();
    }
    Object result = method.invoke(targetObject, args);//调用目标对象的目标方法
    //执行后续增强
    afterAdvice.after();

    //返回目标对象的返回值
    return result;
    }
    };
    /**
    * 2、得到代理对象
    */
    Object proxyObject = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    return proxyObject;

    }
    //get和set方法略
    }
  • 将相关参数注入到 ProxyFactory 后就可以通过 createProxy() 方法获取代理对象

    package demo3;

    import org.junit.Test;

    public class Demo3 {
    @Test
    public void tset1() {

    ProxyFactory proxyFactory = new ProxyFactory();//创建工厂
    proxyFactory.setTargetObject(new ManWaiter());//设置目标对象
    //设置前置增强
    proxyFactory.setBeforeAdvice(new BeforeAdvice() {
    @Override
    public void before() {
    System.out.println("客户你好");
    }
    });
    //设置后置增强
    proxyFactory.setAfterAdvice(new AfterAdvice() {
    @Override
    public void after() {
    System.out.println("客户再见");
    }
    });
    Waiter waiter = (Waiter) proxyFactory.creatProxy();
    waiter.server();

    }
    }