JDK动态代理
动态代理用反射技术、类加载技术以及代码生成技术实现代理逻辑的抽取复用以及代理实例的生成获取。用常规方式无法抽取复用相同的代理逻辑,因为目标方法的调用是不同的,只有通过反射的Method来统一目标方法的调用,进而完成代理逻辑的抽取复用,这样每个代理方法调用这个通用的代理逻辑,但是还是有大量的重复代码,大量相同的方法,大量内部结构相同的类,既然都相同,也就是生成的逻辑都一样,那就把这些代理类的生成交给统一的ProxyGenerator来完成。这也消除了全部重复代码,同时也避免了类爆炸。
动态代理解决的是静态代理中的代理逻辑相同但是无法抽取复用的难题,用反射的Method同一目标方法的调用,进而代理逻辑抽取到InvocationHandler中,进而InvocationHandler依赖目标类,代理类统一依赖InvocattionHnadler,因为InvocationHandler中用到了Method,InvocationHandler可以代理任何目标,进而代理类可以代理任何目标,由于代理类的代码是相同的,所以代理类可以用代码生成技术进行统一生成进而消除重复代码。这样所有的重复代码都去除了
动态代理可以为任何类做代理且是在运行时生成,通过调用JDK提供的一个代理工厂Proxy.newProxyInstance来生成代理,这个代理工厂需要配置三个参数:
1.生成的代理类的二进制字节码的加载器以生成代理类的Class实例去实例化代理类以最终被返回调用
2.被代理的接口
3.代理逻辑,此代理逻辑以InvocationHandler的形式通过已生成的代理类Class实例反射调用此代理类的构造器注入到代理实例 它有对目标类的引用,它有装配代理逻辑的通用接口invoke,这个invoke最关键知道代理目标Method,代理类中的方法只需调用这个invoke就好了,ProxyGenerator负责Method分配到各个代理类中的方法。
代理类字节码生成逻辑:
根据传进来的接口能做一下事情:
1.class 代理类 extends Proxy implements 要代理的接口 { //继承Proxy能构造器注入InvocationHandler
2.public 代理类(InvocationHandler h) {
super(h);
3.private static Method 要代理的接口中的方法的Method对象;
4.static {
要代理的接口中的方法的Method对象=Class.forName("要代理的接口的名字")
.getMethod("要代理的接口中的方法的名字",new Class[]{Class.forName}
5.public final 返回类型 要代理的接口中的方法(参数) {
return (返回类型)this.h.invoke(this,要代理的接口中的方法的Method对象,参数);
接口类
package com.life.proxy; public interface IUserDao { public void save(); }
目标对象
package com.life.proxy; public class UserDao implements IUserDao{ @Override public void save() { System.out.println("保存数据"); } }
代理工厂
package com.life.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { private Object target;// 维护一个目标对象 public ProxyFactory(Object target) { this.target = target; } // 为目标对象生成代理对象 public Object getProxyInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开启事务"); // 执行目标对象方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务"); return null; } }); } }
测试类
package com.life.proxy; import org.junit.Test; public class TestProxy { @Test public void testDynamicProxy (){ IUserDao target = new UserDao(); System.out.println(target.getClass()); //输出目标对象信息 IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance(); System.out.println(proxy.getClass()); //输出代理对象信息 proxy.save(); //执行代理方法 } }