动态代理
一.jdk动态代理
首先给出代码
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface Cloth{ // String brand(); int money(int yuan); void color(String name); } //被代理类1 class Nike implements Cloth { @Override public String brand() { return "nike品牌"; } @Override public int money(int yuan) { System.out.println("衣服的价钱是"+yuan+"元"); return yuan; } @Override public void color(String name) { System.out.println("衣服的颜色是"+name+"色"); } } //被代理类2 class Ad implements Cloth{ @Override public String brand() { return "Adidas品牌"; } @Override public int money(int yuan) { System.out.println("衣服的价钱是"+yuan+"元"); return yuan; } @Override public void color(String name) { System.out.println("衣服的颜色是"+name+"色"); } } //代理类工厂,创造代理类对象 class ProxyFactory{ //调用此方法,返回一个代理类的对象 public static Object getProxyInstance(Object obj) {//obj:被代理类的对象,即真实的对象 MyInvocationHandler handler = new MyInvocationHandler(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler); } }
//动态代理逻辑类,必须实现InvocationHandler接口 class MyInvocationHandler implements InvocationHandler{ //维护一个目标对象 private Object target; public MyInvocationHandler(Object target){ this.target=target; } //当通过代理类的对象调用某个方法的时候,就会自动进入到invoke()中 //将被代理类要操作的方法声明在invoke()中 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("在真实对象访问前的逻辑"); //这里的method方法就是代理类调用的方法,也就是被代理类要调用的方法 Object invoke = method.invoke(target, args);
System.out.println(""); return invoke; } } public class ProxyTest { public static void main(String[] args) { Nike nike = new Nike(); Cloth proxyInstance = (Cloth) ProxyFactory.getProxyInstance(nike); proxyInstance.money(1000); String str = proxyInstance.brand(); System.out.println(str); proxyInstance.color("红"); System.out.println(); Ad adidas = new Ad(); Cloth proxyInstance1 = (Cloth) ProxyFactory.getProxyInstance(adidas); proxyInstance1.color("黑"); String brand = proxyInstance1.brand(); System.out.println(brand); proxyInstance1.money(2000); } }
1.JDK动态代理时java.lang.reflect.*包提供的方式,它必须借助于一个接口才能产生代理对象(本例中的 cloth接口)
2.对该接口定义了两个实现类(Nike和Ad),重写了接口中的方法。
3.创建代理类工厂,产生一个代理类对象。newProxyInstance方法包含三个参数,1.类加载器,采用了使用的类本身(Nike或者Ad)的类加载器. 2.把生成的动态代理对象下挂在,即当前传入的对象所属类实现的接口(Cloth)
3.实现方法逻辑的类,即handler。
4.创建了实现代理逻辑的类,要实现该类必须实现java.lang.reflect.InvocationHandler接口。
invoke方法可以实现代理逻辑,proxy就是getProxyInstance方法生成的对象,method就是代理类要调用的方法,args就是调度方法的参数
二.CGLIB动态代理
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodProxy; /** * 静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口, * 这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理 */ import org.junit.Test; import org.springframework.cglib.proxy.MethodInterceptor; import java.lang.reflect.Method; public class CglibTest { @Test public void test(){ //目标对象 UserDao1 target = new UserDao1(); //代理对象 UserDao1 proxy = (UserDao1)new ProxyFactory1(target).getProxyInstance(); //执行代理对象的方法 proxy.save(); } } /** * 目标对象,没有实现任何接口 */ class UserDao1 { public void save() { System.out.println("----已经保存数据!----"); } } /** * Cglib子类代理工厂 * 对UserDao在内存中动态构建一个子类对象 */ class ProxyFactory1 implements MethodInterceptor{ //维护目标对象 private Object target; public ProxyFactory1(Object target) { this.target = target; } //给目标对象创建一个代理对象 public Object getProxyInstance(){ //1.工具类 Enhancer en = new Enhancer(); //2.设置父类 en.setSuperclass(target.getClass()); //3.设置回调函数 en.setCallback(this); //4.创建子类(代理对象) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开始事务..."); //执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务..."); return returnValue; } }
1.CGLIB动态代理不需要被代理类实现接口
三.静态代理
/** * 接口 */ interface IUserDao { void save(); } /** * 接口实现 * 目标对象 */ class UserDao implements IUserDao { public void save() { System.out.println("----已经保存数据!----"); } } /** * 代理对象,静态代理 */ class UserDaoProxy implements IUserDao{ //接收保存目标对象 private IUserDao target; public UserDaoProxy(IUserDao target){ this.target=target; } public void save() { System.out.println("开始事务..."); target.save();//执行目标对象的方法 System.out.println("提交事务..."); } } public class StaticProxyTest { public static void main(String[] args) { //目标对象 UserDao target = new UserDao(); //代理对象,把目标对象传给代理对象,建立代理关系 UserDaoProxy proxy = new UserDaoProxy(target); proxy.save();//执行的是代理的方法 } } /** * 说明: * 优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展. * 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护. */