1.定义
给某个对象提供一个代理对象,由代理对象控制对原对象的引用。
区别:
1.适配器模式:适配器模式改变对象的接口,代理模式不改变接口。
2.装饰器模式:装饰者模式是为了增加功能,代理模式是为了控制。
2.使用场景
1.中介隔离:隔离访问,原对象不能被直接引用时,代理对象可以通过实现相同的接口来间接提供给客户访问。
2.功能增强:扩展原对象的功能。主要负责预处理,过滤,事后对返回结果的处理。比如日志功能,解决乱码问题。
3.使用方法
按代理创建的时期,分为静态代理,动态代理。
静态代理是在源码上创建,并对其编译。
动态代理是在程序运行时,通过反射机制动态创建。
注意:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
3.1 静态代理
1.创建服务接口
public interface Machine { void run();}
2.创建原对象
public class RealMachine implements Machine { private String machineName; public RealMachine(String machineName){ this.machineName = machineName; init(); } @Override public void run() { System.out.println("run " + machineName); } private void init(){ System.out.println("init "+machineName); }}
3.创建代理对象
public class ProxyMachine implements Machine{ private RealMachine realMachine; private String machineName; public ProxyMachine(String machineName){ this.machineName = machineName; } @Override public void run() { if(realMachine == null){ realMachine = new RealMachine(machineName); } System.out.println("start run"); realMachine.run(); System.out.println("stop run"); }}
4.测试
@Test public void testStaticMachine(){ Machine machine = new ProxyMachine("robot 001"); machine.run(); }
静态代理总结
每一个原对象都要创建一个代理类,不适合
3.2 动态代理
1.创建动态代理类
public class DynamicProxyHandler implements InvocationHandler{ private Object object; public DynamicProxyHandler(final Object object){ this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("start proxy run"); Object invoke = method.invoke(object, args); System.out.println("stop proxy run"); return invoke; }}
2.测试
@Test public void testDynamicMachine(){ Machine machine = new RealMachine("robot 002"); Machine proxyMachine = (Machine) Proxy.newProxyInstance( Machine.class.getClassLoader(), new Class[]{Machine.class}, new DynamicProxyHandler(machine)); proxyMachine.run(); }
动态代理总结
代理包:java.lang.reflect.Proxy
JDK动态代理需要使用newProxyInstance方法.
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
三个参数:
1.ClassLoader loader: 指定当前目标对象使用类加载器,获取加载器的方法是固定的
2.Class<?>[] interfaces: 目标对象实现的接口的类型,使用泛型方式确认类型
3.InvocationHandler h 事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
3.3 代理工厂
1.创建代理工厂
public class ProxyFactory { private Object object; public ProxyFactory(Object object){ this.object = object; } public Object getProxyInstance(){ return Proxy.newProxyInstance( object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("start proxyFactory"); Object invoke = method.invoke(object, args); System.out.println("stop proxyFactory"); return invoke; } } ); }}
2.测试
@Test public void testProxyFactory(){ Machine machine = new RealMachine("robot 003"); Machine proxyInstance = (Machine) new ProxyFactory(machine).getProxyInstance(); proxyInstance.printMessage("test"); }
3.4 cglib代理工厂
和JDK代理不同,当目标对象没有实现任何接口时,cglib代理可以对目标对象进行代理。
cglib代理,又名子类代理。它是在内存中构建一个子类对象,从而实现对目标对象功能的扩展。
1.依赖包
asm-2.2.3,asm-commons-2.2.3,asm-util-2.2.3 ,cglib-nodep-2.1_3
2.创建实体
public class CglibMachine{ private RealMachine realMachine; private String machineName; public CglibMachine(){ } public CglibMachine(String machineName){ this.machineName = machineName; } public void run() { if(realMachine == null){ realMachine = new RealMachine(machineName); } System.out.println("start run"); realMachine.run(); System.out.println("stop run"); }}
3.创建工厂
public class CglibProxyFactory implements MethodInterceptor{ private Object object; public CglibProxyFactory(Object object){ this.object = object; } //给目标对象创建一个代理对象 public Object getProxyInstance(){ //工具类 Enhancer enhancer = new Enhancer(); //设置父类 enhancer.setSuperclass(object.getClass()); //设置回调函数 enhancer.setCallback(this); //创建子类 return enhancer.create(); } @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("start cglib proxy"); //执行目标对象方法 Object invoke = method.invoke(object, args); System.out.println("stop cglib proxy"); return invoke; }}
4.测试
@Test public void testCglibFactory(){ CglibMachine machine = new CglibMachine("robot 004"); CglibMachine proxyInstance = (CglibMachine) new CglibProxyFactory(machine).getProxyInstance(); proxyInstance.run(); }