动态代理基本使用(JDK动态代理与CGLib 动态代理)

JDK 动态代理

使用反射机制在方法执行过程中动态地添加功能

Java 实现动态代理主要涉及以下几个类:

  • java.lang.reflect.Proxy: 这是生成代理类的主类,通过 Proxy 类生成的代理类都继承了 Proxy 类,即 DynamicProxyClass extends Proxy。
  • java.lang.reflect.InvocationHandler: 这里称他为"调用处理器",他是一个接口,我们动态生成的代理类需要完成的具体内容需要自己定义一个类,而这个类必须实现 InvocationHandler 接口。

 

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

 

import org.junit.Test;

 

/**

 * JDK 动态代理

 */

public class JdkProxyTest {

 

    public Object getProxy(final Object target) {

 

       return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),

              new InvocationHandler() {

                  @Override

                  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

 

                     if (Object.class.equals(method.getDeclaringClass())) {

                         return method.invoke(this, args);

                     }

                     System.out.println("[before] The method");

 

                     // 调用目标方法

                     Object result = null;

                     try {

                         // 前置通知

                         result = method.invoke(target, args);

                         // 返回通知, 可以访问到方法的返回值

                     } catch (NullPointerException e) {

                         e.printStackTrace();

                         // 异常通知, 可以访问到方法出现的异常

                     }

                     // 后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值

                     // 打印日志

                     System.out.println("[after] The method");

                     return result;

                  }

              });

    }

 

    @Test

    public void test() {

       ITarget target = new Target();

 

       JdkProxyTest proxy = new JdkProxyTest();

 

       ITarget targetProxy = (ITarget) proxy.getProxy(target);

 

       targetProxy.exec();

    }

 

}

 

interface ITarget {

    void exec();

}

 

class Target implements ITarget {

    public void exec() {

       System.out.println("正在执行方法");

    }

}

缺点:目标对象必须实现接口,不能针对类创建代理类


CGLib 动态代理

简述

           Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理

import java.lang.reflect.Method;

 

import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

 

public class CglibTest {

 

    public static Object ceateProxtObject(final Object object, Class clazz) {

       // 声明增加类实例

       Enhancer en = new Enhancer();

       // 设置被代理类字节码,CGLIB根据字节码生成被代理类的子类

       en.setSuperclass(clazz);

       // 设置回调函数,即一个方法拦截

       en.setCallback(new MethodInterceptor() {

 

           /**

            * Object表示要进行增强的对象

            * Method表示拦截的方法

            * Object[]数组表示参数列表,基本数据类型需要传入其包装类型,如int-->Integerlong-Longdouble-->Double

            * MethodProxy表示对方法的代理,invokeSuper方法表示对被代理对象方法的调用

            */

           @Override

           public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

              System.out.println("[before] The method");

 

              // 注意参数object,仍然为外部声明的源对象,且MethodJDKMethod反射

              // Object o = method.invoke(object, args);

              Object o = proxy.invokeSuper(obj, args);

 

              System.out.println("[after] The method");

              return o;

           }

       });

       return en.create();

    }

 

    public static void main(String[] args) {

//     // 未实现接口的类的代理

//     Person proxyPerson = (Person) CglibTest.ceateProxtObject(new Person(), Person.class);

//     proxyPerson.exec();

 

       // 实现接口的类的代理

       ITarget proxyTarget = (ITarget) CglibTest.ceateProxtObject(new Target(), Target.class);

       proxyTarget.exec();

    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值