Java 动态代理
2016-02-25 11:46
344 查看
一、动态代理的由来
代理是指:给每个具体类写一个代理类,以后要使用某个具体的类时,只要创建它的代理类的对象,然后调用代理类的方法就可以了,可是如果现在有很多具体的类,那就需要创建很多的代理类才可以,这样显然很不合适,那动态代理就应运而生。
二、Java实现动态代理有2种方式:
1、JDK实现动态代理,但是它需要实现类通过接口定义业务方法,对于没有接口的类是无法实现的;
2、CGLib,它采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用。
JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
三、JDK的实现
此类型的动态代理使用到了一个接口InvocationHandler和一个代理类Proxy,这两个类配合使用即可实现动态代理。
四、CGLib实现
六、比较两种方式的优缺点
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib更合适,反之使用JDK方式要更好些。同时,用于CGLib采用的动态代理创建子类的方式,对于final方法,无法进行处理。
代理是指:给每个具体类写一个代理类,以后要使用某个具体的类时,只要创建它的代理类的对象,然后调用代理类的方法就可以了,可是如果现在有很多具体的类,那就需要创建很多的代理类才可以,这样显然很不合适,那动态代理就应运而生。
二、Java实现动态代理有2种方式:
1、JDK实现动态代理,但是它需要实现类通过接口定义业务方法,对于没有接口的类是无法实现的;
2、CGLib,它采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用。
JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
三、JDK的实现
此类型的动态代理使用到了一个接口InvocationHandler和一个代理类Proxy,这两个类配合使用即可实现动态代理。
//接口 interface InterfaceClass { void show() ; } //具体实现类A class ClassA implements InterfaceClass { @Override public void show(){ System.out.println("class A") ; } } //具体实现类B class ClassB implements InterfaceClass { @Override public void show(){ System.out.println("class B") ; } } //动态代理类,实现InvocationHandler接口 class Invoker implements InvocationHandler { InterfaceClass ia ; public Invoker(InterfaceClass ia) { this.ia = ia ; } @Override public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable { method.invoke(ia, arg) ; return null ; } } // Test class DynamicProxyTest{ public static void main(String[] args){ // 创建具体类ClassA的处理对象 Invoker invoker1 = new Invoker(new ClassA()); // 获得具体类ClassA的代理 InterfaceClass ic1 = (InterfaceClass)Proxy.newProxyInstance(InterfaceClass.class.getClassLoader(), new Class[]{InterfaceClass.class}, invoker1); ic1.show() ; // classB也是如此 } }
四、CGLib实现
public class CGLIBProxy implements MethodInterceptor{ private Enhancer enhancer = new Enhancer() ; public Object getProxy(Class clazz) { // 设置父类 enhancer.setSuperclass(clazz); enhancer.setCallback(this); // 通过字节码技术动态创建子类实力 return enhancer.create() ; } // 所有的方法都会被这个方法所拦截,该类实现了子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class类创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,args为方法动态入参,proxy为代理类实例。 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodproxy) throws Throwable{ Object result = methodproxy.invokerSuper(obj, args) ; return result ; } } public class UserServiceImpl{ public void sayHello() { System.out.println("sayHello method") ; } public void sayBye() { System.out.println("sayBye method") ; } } // Test public class Test{ public static void main(String[] args) { CGLIBProxy proxy = new CGLIBProxy() ; UserServiceImpl impl = (UserServiceImpl)proxy.getProxy(UserServiceImpl.class) ; impl.sayHello() ; } }
六、比较两种方式的优缺点
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib更合适,反之使用JDK方式要更好些。同时,用于CGLib采用的动态代理创建子类的方式,对于final方法,无法进行处理。
相关文章推荐
- 10个影响JavaEE性能问题
- 集成 Maven 2 插件到 Eclipse 的过程
- Java编程提高性能时需注意的地方总结
- Java基础:Day11笔记内容 (内部类、权限修饰符 )
- 使用Java8实现观察者模式的方法(上)
- java 基础之工厂
- Java语法糖之foreach
- Java语法糖之foreach
- java中public等权限问题和final的使用
- Java基础:Day10笔记内容 (多态概述、抽象类)
- JAVA 判断一个字符串是不是一个合法的日期格式format.setLenient(false);
- Eclipse(集成开发环境)
- java回顾之socket通信
- java springMVC生成二维码
- Mybatis/Ibatis例子(添加,修改,删除)
- eclipse使用时技巧与注意事项
- java 四种写文件比较
- 多线程下载原理
- spring(基础10) 注解@Value详解
- Java中常见的IO流及其使用