今天学习了代理模式,心血来潮便做做笔记
代理模式有两种:静态代理,动态代理
含义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
例如生活中的汽车中介,客户觉得自己去车店看车太辛苦了,于是找到了中介,中介这里什么车都有,但是价钱会更贵一点。
为什么要使用代理模式?
1、遵循开闭原则,方便扩展。代理可以做一些额外的事情
2、遵循依赖倒置,降低类之间的耦合
缺点:每次都要创建代理类实现接口,所以就有了动态代理
静态代理:
//买汽车接口
package com.mode.daili; public interface BuyCar { void buyCar(); //买汽车 }
//客户类
package com.mode.daili; public class Customer implements BuyCar { @Override public void buyCar() { System.out.println("我要买车"); } }
//代理
package com.mode.daili; public class Daili implements BuyCar { private Customer customer; public Daili(Customer customer) { this.customer = customer; } @Override public void buyCar() { System.out.println("请跟我先看车"); //买车前做的事 customer.buyCar(); System.out.println("请支付Money"); //买车后做的事 } }
//测试
package com.mode.daili; public class Main { public static void main(String[] args) { BuyCar daili = new Daili(new Customer()); daili.buyCar(); } }
结果
动态代理:
1、jdk动态代理
2、cglib动态代理
创建jdk代理类
package com.mode.proxy.dongtai.homework1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //jdk代理类 public class MyInvocationHandlerJDK implements InvocationHandler { private Object target; public MyInvocationHandlerJDK(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK代理类");//可以在被代理类方法使用前后做其它操作 Object obj = method.invoke(target, args);//使用方法 return obj; } }
package com.mode.proxy.dongtai.homework1; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; //创建cglib代理类 public class MyInvocationHandlerCglib implements MethodInterceptor { private Object target; public MyInvocationHandlerCglib(Object target) { this.target = target; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("Cglib代理此方法");//可以在被代理类方法使用前后做其它操作 Object result = methodProxy.invoke(target,objects); //使用方法 return result; } }
//工具类
package com.mode.proxy.dongtai.homework1; import net.sf.cglib.proxy.Enhancer; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; /** * 工具类 */ public class ProxyGenerator { //把对象代理的方法,如果对象有实现接口,就使用jdk代理,否则Cglib代理 public Object generate(Object target){ Class>[] interfaces = target.getClass().getInterfaces(); if(interfaces.length > 0){ return generateJDK(target); }else { return generateCglib(target); } } //Cglib代理方法 private Object generateCglib(Object target) { Enhancer enhancer = new Enhancer(); //setSuperclass:设置被代理类的父类 //setCallback:指定谁代理 enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new MyInvocationHandlerCglib(target)); return enhancer.create();//创建被代理后的对象并返回 } //jdk代理方法 private Object generateJDK(Object target){ //创建代理类对象 InvocationHandler handler = new MyInvocationHandlerJDK(target); //Proxy.newProxyInstance() //第一个参数:被代理类的类加载对象 //第二个参数:被代理类的所有接口 //第三个参数:指定谁代理 Object obj = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler ); return obj; //返回被代理后的对象 } }
测试类
package com.mode.proxy.dongtai.homework1; public class Main { public static void main(String[] args) { ProxyGenerator proxy = new ProxyGenerator(); Book book = new Book(); Book generate = (Book) proxy.generate(book); generate.printBook(); } }
jdk代理和cglib代理的区别
jdk代理:只能代理实现了接口的类的接口方法,不需要导入jar包;
cglib代理:可以代理没有实现接口的类,但需要导入jar包: asm-7.1 cglib-3.3.0
可自行去这里下:https://mvnrepository.com/
以上方法均已测试过,不足之处,多多见谅