SpringAOP--代理

前言

  在Spring或者SpringBoot中,可以通过@Aspect注解和切点表达式等配置切面,实现对某一功能的织入。然而其内部到底是如何实现的呢?

  实际上,Spring在启动时为切点方法所在类生成了代理类,通过操作代理类代替操作实际类,从而实现在真正调用方法之前或之后,插入一些我们自定义的逻辑。

  如何生成代理类呢?

     

JDK动态代理

  • JDK动态代理要求 被代理类必须有接口抽象。
  • 通过实现  InvocationHandler 接口并实现  invoke(Object proxy, Method method, Object[] args) 方法进行自定义逻辑的织入:
    • proxy :当前的代理类实例;
    • method:被代理的方法;
    • args:方法入参;

invoke方法的官方说明如下:即在

* Processes a method invocation on a proxy instance and returns
* the result. This method will be invoked on an invocation handler
* when a method is invoked on a proxy instance that it is
* associated with. 

  使用示例:

1、被代理的方法:

// 方法实现
public class HelloAOPImpl implements HelloAOP {
    @Override
    public String sayHello() {
        String hello = "你好,AOP";
        System.out.println(hello);
        return hello;
    }
}
View Code

 

  

2、配置自定义调用处理器

public class MyInvocationHandler implements InvocationHandler {
    private Object target;
  // 通过构造函数将配代理对象注入
    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    //回调
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是代理,有人让我对你说:");
        /**调用前,自定义业务*/
        Object res = method.invoke(target, args);
        /**调用后,自定义业务*/
        return res;
    }
    //获取代理类实例
    public <T> T getProxyInstance(){
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

      2:调用与输出:

public static void main(String[] args) {
        HelloAOPImpl helloAOP = new HelloAOPImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(helloAOP);
        HelloAOP proxy = myInvocationHandler.getProxyInstance();
        proxy.sayHello();
 }

// 输出
我是代理,有人让我对你说:
你好,AOP
View Code 

一个疑问:代理类如何取代被代理类的呢?

CGLIB动态代理

 CGLIB动态代理不需要代理对象实现某个接口:

1、被代理类(没有接口实现)

public class HelloAOPImpl2 {
    public void sayHello() {
        String s = "你好,AOP";
        System.out.println(s);
    }
}
View Code

 

 

2、CGLIB代理

public class CgibAOP2 implements MethodInterceptor {
    private Object target;

    /**
     * 通过构造函数设置被代理对象
     * @param target
     */
    public CgibAOP2(Object target) {
        this.target = target;
    }

    /**
     * 回调该方法。
     * @param o
     * @param method
     * @param objects
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("say之前:"+ method+"1");
        Object res = method.invoke(target, objects);
        System.out.println("say之后:"+ method+"1");
        return res;
    }

    /**
     * 生成代理实例
     * @return
     */
    public Object getProxy(){
        // 通过增强实现
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this); //设置回调
        Object res = enhancer.create();
        return res;
    }
}

 

3、测试:

public class Test {
    public static void main(String[] args) {
        HelloAOPImpl2 helloAOP = new HelloAOPImpl2();
        HelloAOPImpl2 proxy =  (HelloAOPImpl2)new CgibAOP2(helloAOP).getProxy();
        proxy.sayHello();
    }
}
View Code

 

输出:

say之前:public void com.wht.springaop.DynamicProxy.Cglib.HelloAOPImpl2.sayHello()1
你好,AOP
say之后:public void com.wht.springaop.DynamicProxy.Cglib.HelloAOPImpl2.sayHello()1
View Code

 

posted @ 2019-09-01 19:09  一碗雪花  阅读(250)  评论(0编辑  收藏  举报