一:什么是动态代理:java
利用反射机制在运行时建立代理类。接口、被代理类不变。程序员
二:动态代理和静态代理的不一样:ide
一、静态代理的代理类是程序员事先写好的函数
二、动态代理的代理类是在程序运行时动态生成的this
三:动态代理分为两大类:spa
一、基于接口的动态代理代理
二、基于类的动态代理日志
四:动态代理的三种实现方式:code
一、基于接口--->JDK动态代理 (JAVA原生的)(咱们在这里使用)对象
二、基于类--->cglib (本身查阅资料作了解)
三、java字节码实现---> javassist (查资料了解)
五:在使用动态代理以前,首先了解两大类
一、Proxy (代理)
二、InvocationHandler (调用处理程序)
六:动态代理代码展现 (房东出租房子案例)
一、建立一个抽象角色
1 //租房的接口 (抽象角色) 2 3 public interface Rent { 4 5 //出租的方法 6 void rent(); 7 8 }
二、建立真实角色,实现抽象角色接口
1 //房东 要出租房子 (真实的角色) 2 3 public class Host implements Rent { 4 @Override 5 public void rent() { 6 System.out.println("房东要出租房子"); 7 } 8 }
三、首先,咱们构建一个类来实现InvocationHandler接口
1 //动态生成代理 2 3 public class ProxyInvocationHandler implements InvocationHandler { 4 5 //被代理的接口 6 private Rent rent; 7 8 public void setRent(Rent rent) { 9 this.rent = rent; 10 } 11 12 // Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), 13 // new Class<?>[] { Foo.class }, 14 // handler); 15 16 //生成获得代理类 (经过Proxy类的静态方法newProxyInstance返回一个接口的代理实例。针对不一样的代理类,传入相应的代理程序控制器InvocationHandler) 17 public Object getProxy(){ 18 return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this); 19 20 } 21 22 //处理代理实例,并返回结果 23 @Override 24 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 25 26 //动态代理的本质,就是使用反射机制实现! 27 seeHouse(); 28 Object result = method.invoke(rent, args); 29 fare(); 30 return result; 31 } 32 33 public void seeHouse(){ 34 System.out.println("中介带看房子!"); 35 } 36 public void fare(){ 37 System.out.println("收中介费!"); 38 } 39 }
四、执行动态代理
1 //执行动态代理,实现租房方法 2 3 public class Client { 4 public static void main(String[] args) { 5 //真实角色 6 Host host = new Host(); 7 8 //代理角色,如今没有 9 ProxyInvocationHandler pih = new ProxyInvocationHandler(); 10 //经过调用程序来处理咱们要调用的接口对象! 11 pih.setRent(host); 12 13 Rent proxy = (Rent) pih.getProxy(); //这里的proxy是动态生成的,咱们并无写! 14 //调用租房方法 15 proxy.rent(); 16 17 } 18 }
五、输出结果
七:动态代理的具体步骤
一、经过实现 InvocationHandler 接口建立本身的调用处理器;
二、经过为 Proxy 类指定 ClassLoader 对象和一组 interface 来建立动态代理类;
三、经过反射机制得到动态代理类的构造函数,其惟一参数类型是调用处理器接口类型;
四、经过构造函数建立动态代理类实例,构造时调用处理器对象做为参数被传入。
八:动态代理的好处
一、可使真实角色的操做更加纯粹!不用去关注一些公共的业务
二、公共业务就交给代理角色!实现了业务的分工!
三、公共业务发生扩展的时候,方便集中管理
四、一个动态代理类代理的是一个接口,通常就是对应的一类业务
五、一个动态代理类能够代理多个类,只要是实现了同一个接口便可
九:根据上述的动态代理实现机制,咱们能够衍生出一个万能的动态代理类
1 //万能的动态代理类 2 3 public class ProxyInvocationHandler implements InvocationHandler { 4 5 //被代理的接口 6 private Object target; 7 8 public void setTarget(Object target) { 9 this.target = target; 10 } 11 12 // Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), 13 // new Class<?>[] { Foo.class }, 14 // handler); 15 16 //生成获得代理类 17 public Object getProxy(){ 18 return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); 19 20 } 21 22 //处理代理实例,并返回结果 23 @Override 24 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 25 26 //动态代理的本质,就是使用反射机制实现! 27 log(method.getName()); 28 Object result = method.invoke(target, args); 29 return result; 30 } 31 32 //根据不一样业务须要,建立不一样的扩展方法 (此处为打印日志) 33 public void log(String msg){ 34 System.out.println("执行了"+msg+"方法!"); 35 } 36 }
执行动态代理:
1 //执行动态代理 2 3 public class Client { 4 public static void main(String[] args) { 5 //真实角色 6 UserServiceImpl userService = new UserServiceImpl(); 7 8 //代理角色,不存在 9 ProxyInvocationHandler pih = new ProxyInvocationHandler(); 10 11 //设置要代理的对象 12 pih.setTarget(userService); 13 14 //动态生成代理类 15 UserService proxy = (UserService) pih.getProxy(); 16 17 proxy.update(); 18 19 } 20 }
注:抽象角色、真实角色 的实际代码此处省略(与静态代理实现步骤同样)
【咱们可根据不一样的业务需求,套用万能动态代理模板便可】