【JAVA 之动态代理(一)】

永久链接: http://gaojingsong.iteye.com/blog/2285271

预览文章: 设计模式之代理模式

 

静态代理类优缺点

优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。 

缺点: 

1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。 

2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。 

另外,如果要按照上述的方法使用代理模式,那么真实角色(委托类)必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色(委托类),该如何使用代理呢这个问题可以通过Java的动态代理类来解决。

 

动态代理分为两种:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。其中JDK提供的动态代理必须提供接口,而cglib则不需要提供接口。java的JDK动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

 

JDK代理的实现步骤是:

1)提供接口

2)提供接口的实现类

3)编写代理类,实现InvoCationHandler接口

 

 

源码案例:

1)定义接口

package demo;

public interface KindWomen {

    // 定义一种类型的女人,王婆和潘金莲都属于这个类型的女人

    public void makeEyesWithMan();// 抛媚眼

}

2)实现接口

package demo;

//潘金莲是什么样的人

public class PanJinLian implements KindWomen {

    public void makeEyesWithMan() {

        System.out.println("潘金莲抛媚眼...");

    }

}

3)编写代理类

package demo;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

 

public class ProxyWomen implements InvocationHandler {

 

private Object target;

 

public Object bind(Object target){

this.target = target;

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

target.getClass().getInterfaces(), this);

}

@Override

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

throws Throwable {

Object result = method.invoke(target, args);  

        return result;  

}

 

}

 

4) 测试

package demo;

 

public class DemoMain {

/**

* @param args

*/

public static void main(String[] args) {

ProxyWomen proxyWomen = new ProxyWomen();

KindWomen kindWomen = (KindWomen) proxyWomen.bind(new PanJinLian());

kindWomen.makeEyesWithMan();

}

 

}

 

 



 动态代理类优缺点

优点 

1.动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。 

2.动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。

缺点 

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

一个典型的动态代理创建对象过程可分为以下四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))

猜你喜欢

转载自gaojingsong.iteye.com/blog/2393911