java的动态代理机制详解--20

来源:互联网 发布:下载中文ae软件 编辑:程序博客网 时间:2024/05/29 14:17

java的动态代理机制详解--20

@设计模式——代理模式——静态代理的实现

1、聚合代理优于继承代理。因为实现功能叠加的情况下,聚合代理通过相互代理可以实现功能重用,而继承代理必须写多个类来实现多功能叠加。2、但静态代理只能代理一种类型的被代理类,换个类型的就不行了,这需要动态代理静态代理的两种实现方式对比(继承方式和聚合方式)

案例--代理类功能的叠加

1. 继承的方式:

如果使用继承的方式来实现我们代理功能的叠加,我们的代理类会无限的膨胀下去。

2. 聚合的方式:

由于代理类和被代理类都实现了相同的接口,那么代理类的构造参数就可以传入该相同的接口,这样在后面功能叠加的时候就可以传入其他功能的代理类,因为他们都实现了相同的父接口。从而达到功能叠加的作用。
public interface Moveable {void move();}
public class CarTimeProxy implements Moveable {public CarTimeProxy(Moveable m) {super();this.m = m;}private Moveable m;@Overridepublic void move() {long starttime = System.currentTimeMillis();System.out.println("汽车开始行驶....");m.move();long endtime = System.currentTimeMillis();System.out.println("汽车结束行驶....  汽车行驶时间:" + (endtime - starttime) + "毫秒!");}}
public class Car implements Moveable {@Overridepublic void move() {//实现开车try {Thread.sleep(new Random().nextInt(1000));System.out.println("汽车行驶中....");} catch (InterruptedException e) {e.printStackTrace();}}}
eg:汽车类,先记录日志再记录时间Car car = new Car();CarTimeProxy ctp = new CarTimeProxy(car);CarLogProxy clp = new CarLogProxy(ctp);clp.move();先记录时间再记录日志Car car = new Car();CarLogProxy clp = new CarLogProxy(car);CarTimeProxy ctp = new CarTimeProxy(clp);ctp.move();
聚合的方式比继承的方式灵活很多,通过聚合的方式,代理之间也是可以相互传递的,相互组合。


JDK动态代理

1. 目的:动态产生代理,实现对【不同类】,【不同方法】的代理
2. java动态代理类,位于java.lang.reflect包下,一般涉及两个类:

(1)Interface InvocationHandler:

该接口中仅定义了一个方法public object invoke(Object obj,Method method,Object[] args):实际使用中,
obj指被代理类的对象,
method指被代理的方法,
args为该方法参数数组。
这个抽象方法在代理类中动态实现。实现该接口即为代理的事务处理器。

(2)Proxy:该类即为动态代理类:

static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以被当作代理类使用(可使用被代理类的在【接口中】声明过的方法)。
  第一个参数loader为被代理类的加载器,通过被代理类.getClass().getClassLoader()得到· 第二个参数interfaces为被代理类实现的所有接口,同样通过getClass().getInterfaces()得到· 第三个参数handler就是自己实现的InvocationHandler的实现类的对象

3. 动态代理实现:

1) 声明一个代理h实现InvocationHandler接口,通过【构造方法接受被代理类】,并实现invoke方法,添加业务逻辑(实现原有功能并添加额外功能)2) 在测试类中,通过共同实现接口的实例获得代理对象,并实现方法,如Interface1 i = (Interface1)Proxy.newProxyInstance(classLoader,classInterfaces,h);3) 通过动态代理对象m,代用其方法i.fun();



相关代码——(上):@Car.javapublic class Car implements Moveable{public void move() {//实现打车try {Thread.sleep(new Random().nextInt(1000));System.out.println("车行驶中...");} catch (Exception e) {e.printStackTrace();}}public void move1() {// TODO Auto-generated method stubSystem.out.println("move1");}}@TimeHandler.javapublic class TimeHandler implements InvocationHandler {private Object target;public TimeHandler(Object target) {super();this.target = target;}/*** 参数:* proxy:被代理对象;method:被代理对象的方法;args:方法的参数。* 返回值:* Object:方法的返回值。*/public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {long starttime=System.currentTimeMillis();System.out.println("车开始行驶...");method.invoke(target);//通过反射机制:Method是一个方法,方法对象。Method.Invoke()相当于method();long endtime=System.currentTimeMillis();System.out.println("车结束行驶。");System.out.println("车行驶时间:"+(endtime-starttime)+"毫秒!");return null;}}

相关代码——(下):@TestJDKProxy.javapublic class TestJDKProxy {/*** JDK动态代理测试类*/public static void main(String[] args) {Car car=new Car();InvocationHandler h=new TimeHandler(car);Class<?> cls=car.getClass();/*** 参数:loader:类加载器;interface:实现接口;h:InvocationHandler。*/Moveable m=(Moveable) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);m.move();m.move1();/*** 执行顺序:m.move()后先执行TimeHandler类中的invoke()方法,* 当执行到method.invoke(target);时,再去执行目标类Car的move()方法,* 然后返回method.invoke(target);的下一句,最后返回这里执行完毕。*/}}@Moveable.javapublic interface Moveable {void move();void move1();}

一、JDK与CGLIB动态代理的区别

1、JDK:针对接口

· 只能代理【实现了接口的类】· 没有实现接口的类不能实现JDK的动态代理

2、CGLIB:针对类

· 针对类来实现代理的· 对指定目标类产生一个子类,通过方法拦截【技术拦截】所有父类方法的调用
· 注意:CGLIB不能对“final”修饰的类进行代理。

二、CGLIB:是一个强大的开源项目,可以在运行期扩展Java类与实现Java接口。

相关代码——(上):@Client.javapublic class Client {public static void main(String[] args) {//创建代理类返回对象CglibProxy proxy=new CglibProxy();//得到代理类的对象Train t=(Train) proxy.getProxy(Train.class);t.move();/*** 执行顺序(类似JDK动态代理):从proxy.getProxy(Train.class);后,开始先执行CglibProxy类的getProxy()方法,* 再返回到t.move();后,接着执行CglibProxy类的intercept()方法,等到methodproxy.invokeSuper();则执行Train类中的move()方法,* 然后返回到methodproxy.invokeSuper();下一句直到最后,再接着返回到Client类,完毕。*/}}

@Train.javapublic class Train {public void move(){System.out.println("火车行驶中...");}}
相关代码——(下):@CglibProxy.javapublic class CglibProxy implements MethodInterceptor {private Enhancer enhancer=new Enhancer();// 得到代理类public Object getProxy(Class cls){//设置创建子类的类enhancer.setSuperclass(cls);enhancer.setCallback(this);//返回子类的实例return enhancer.create();}/*** 参数:object:拦截所有目标类方法的调用,* method:目标方法的反射对象,* args:方法的参数,* methodproxy:代理类的实例。*/public Object intercept(Object object, Method method, Object[] args,MethodProxy methodproxy) throws Throwable {syso("日志开始...");//代理类调用父类的方法methodproxy.invokeSuper(object, args);syso("日志结束...");return null;}}








0 0
原创粉丝点击