静态代理:
java代理是一种模式--代理模式。采用代理模式,可以在不改变目标类代码的基础上,通过代理对象,来增加额外的功能(比如增加日志检测等)或者只需要目标对象的部分行为。
java中,代理分为静态代理和动态代理。
静态代理:我的理解是程序员自己或者用某些工具去自己创建或者生成代理类。在使用之前,代理类已经存在。
动态代理:区别于静态代理,它是动态的,不需要程序员去自己创建,只需要采用现成的动态代理类库(jdk动态代理,cglib)调用某些类的某些方法,动态生成代理类。代理类在使用之前是不存在的。什么时候使用,什么时候创建。是动态的。
静态代理:
静态代理有两种实现方式。
1.合成
即将目标类作为代理类的全局成员。需要目标类实现接口
接口:
package com.wtd.staticproxy; public interface Moveable { void move(); }
目标类:
package com.wtd.staticproxy; import java.util.Random; /** * @desc Car:被代理对象,真实对象 * */ public class Car implements Moveable { @Override public void move() { try { System.out.println("the car is running"); Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
代理类:
package com.wtd.staticproxy; /** * @desc 静态代理 第二种方式:合成。 * 静态代理,说白了,就是手动创建 代理类。手动创建的两种方式[继承,合成] * */ public class Car2 implements Moveable {//代理类:必须和被代理类都实现统一的接口 Car car;//被代理类类 (真实类) public Car2(Car car) { super(); this.car= car; } @Override public void move() { System.out.println("the car start");//业余方法 long startTime= System.currentTimeMillis();//业余方法 car.move();//调用被代理类的功能方法 long endTime= System.currentTimeMillis();//业余方法 System.out.println("the car stop,use time:"+ (endTime-startTime)+"ms");//业余方法 } }
测试类:
package com.wtd.staticproxy; public class Test { /** * @param args */ public static void main(String[] args) { Car car = new Car();//创建被代理类(真实类) Moveable m2= new Car2(car);//创建代理类 m2.move(); } }
output:
the car start
the car is running
the car stop,use time:681ms
2.继承
代理类继承目标类。不需要目标类继承接口。但是目标类必须不能被final修饰
目标类:
package com.wtd.staticproxy; import java.util.Random; /** * @desc Car:被代理对象,真实对象 * */ public class Car { public void move() { try { System.out.println("the car is running"); Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
代理类:
package com.wtd.staticproxy; /** * @desc 静态代理有两种方式, 这是第一种:继承的方式、 * 第二种:合成 * */ public class Car1 extends Car{ @Override public void move() { System.out.println("汽车开始行驶");//业余方法 long startTime= System.currentTimeMillis();//业余方法 super.move();//调用父类的功能方法 long endTime= System.currentTimeMillis();//业余方法 System.out.println("汽车行驶结束,行驶了:"+ (endTime- startTime)+"毫秒");//业余方法 } }
测试类:
package com.wtd.staticproxy; public class Test { /** * @param args */ public static void main(String[] args) { Car m= new Car1(); m.move(); } }
output:
the car start
the car is running
the car stop,use time:361ms
动态代理:
原理:类似于静态代理中的合成。被代理对象必须继承某一接口
接口:
package com.wtd.dynamicproxy3; public interface Moveable { void move(); void run(String args); }
目标对象(被代理对象):
package com.wtd.dynamicproxy3; public class Car implements Moveable { @Override public void move() { System.out.println("Car move()"); } @Override public void run(String args) { System.out.println("Car run()"+ args); } }
调用处理器对象:InvocationHandler对象
package com.wtd.dynamicproxy3; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LogHandler implements InvocationHandler { private Object proxied; public LogHandler(Object proxied) { this.proxied= proxied; // TODO Auto-generated constructor stub } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "----------proxy: " + proxy.getClass() + ", method: " + method+ ", args: " + args+ ", proxied: " + proxied.getClass()); return method.invoke(proxied, args); } }
测试类:
package com.wtd.dynamicproxy3; import java.lang.reflect.Proxy; public class TestDynamicProxy { public static void main(String[] args) { Car car= new Car(); Moveable m= (Moveable) Proxy.newProxyInstance(Moveable.class.getClassLoader(), new Class<?>[]{Moveable.class}, new LogHandler(car)); m.move(); m.run("haha"); } }
output:
----------proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.wtd.dynamicproxy3.Moveable.move(), args: null, proxied: class com.wtd.dynamicproxy3.Car
Car move()
----------proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.wtd.dynamicproxy3.Moveable.run(java.lang.String), args: [Ljava.lang.Object;@5e743399, proxied: class com.wtd.dynamicproxy3.Car
Car run()haha
cglib动态代理:
原理:类似于静态代理中的继承方式。被代理对象的类不能被final所修饰
首先需要导入jar包:cglib-nodep-x.x.x.jar。可在mvnrepository下载。
被代理类:父类:realObject:
package com.wtd.cglibproxy; /** * 目标类;父类;被代理类 * 不能被final所修饰 * */ public class Car { public void move() { System.out.println("the car running"); } }
方法拦截器类:
package com.wtd.cglibproxy; 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 CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); /** * 设置获得代理对象(即子类对象)的方法 * 需要用到 Enhancer * */ public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** * @author WesTward * @param proxied:被代理对象,目标对象,父类对象 * @param method: 目标对象的 方法 * @param args: 目标对象的方法的参数 * @param proxy: 代理对象 * */ @Override public Object intercept(Object proxied, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Log---------start"); proxy.invokeSuper(proxied, args); System.out.println("Log---------end"); return null; } }
测试类:
package com.wtd.cglibproxy; public class Test { /** * @param args */ public static void main(String[] args) { CglibProxy cglibProxy= new CglibProxy(); Car car = (Car) cglibProxy.getProxy(Car.class); car.move(); } }
output:
Log---------start
the car running
Log---------end
附:
动态代理主要运用了java的反射机制。