静态代理:
静态代理的实现要求:真实角色,代理角色;真实角色和代理角色要实现同一个接口,代理角色要持有真实角色的引用。
在Java中线程的设计就使用了静态代理设计模式,其中自定义线程类实现Runable接口,Thread类也实现了Runalbe接口,
在创建子线程的时候,传入了自定义线程类的引用,再通过调用start()方法,调用自定义线程对象的run()方法。实现了线程的并发执行。
需求:在被代理类执行方法的时候,能够打印日志信息,比如当前的时间节点
1、业务方法,被代理类和代理类都要实现这个接口:
public interface LogService { void logTime(); }
2、被代理类
public class BeProxy implements LogService{ public void logTime() { System.out.println("被代理类执行了~"); } }
3、代理类:代理角色实现被代理类需要的功能。
public class Proxy implements LogService { // 持有代理角色的引用 private BeProxy beProxy; public Proxy() { } public Proxy(BeProxy beProxy) { this.beProxy = beProxy; } public void logTime() { System.out.println(new SimpleDateFormat("HH:mm:ss SSS").format(new Date(System.currentTimeMillis())) + " 代理对象开始执行"); // 执行的是被代理角色的功能 beProxy.logTime(); System.out.println(new SimpleDateFormat("HH:mm:ss SSS").format(new Date(System.currentTimeMillis())) + " 代理对象结束执行"); } }
4、测试
public class Test { public static void main(String[] args) { // 被代理对象 BeProxy beProxy = new BeProxy(); // 代理者对象 Proxy proxy = new Proxy(beProxy); proxy.logTime(); } }
5、结果:
00:48:21 119 代理对象开始执行
被代理类执行了~
00:48:21 121 代理对象结束执行
动态代理案例一:
动态代理和静态代理角色一样
态代理的代理类是动态生成的,不是我们直接写好的!
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口--- JDK动态代理 [我们在这里使用]
- 基于类: cglib
- java字节码实现 : javasist
需要了解两个类:
java.lang.reflect.Proxy; 代理, static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。 java.lang.reflect.InvocationHandler: 调用处理程序 Object invoke(Object proxy, Method method, Object[] args) 在代理实例上处理方法调用并返回结果。
动态代理具体步骤:
- 通过实现 InvocationHandler 接口创建自己的调用处理器;
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
1、业务方法
public interface LogService { void logTime(); }
2、被代理类
public class BeProxy implements LogService{ @Override public void logTime() { System.out.println("被代理类执行了~"); } }
3、处理程序类,可以自动生成代理类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 处理程序类,用这个类可以自动生成代理类 public class ProxyInvocationHandler implements InvocationHandler { // 被代理的接口 private LogService logService; public void setLogService(LogService logService) { this.logService = logService; } // 生成得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),logService.getClass().getInterfaces(),this); } @Override /**处理代理实例,并返回结果*/ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object invoke = method.invoke(logService, args); return invoke; } }
4、测试类
public class Test { public static void main(String[] args) { // 真实角色 BeProxy proxy = new BeProxy(); // 代理角色【不存在】 ProxyInvocationHandler handler = new ProxyInvocationHandler(); // 设置要代理的对象 handler.setLogService(proxy); // 生成代理类对象 LogService logService = (LogService) handler.getProxy(); // 执行角色方法 logService.logTime(); } }
5、结果
被代理类执行了~
动态代理案例二:
需求:
需求: 有一个service接口,调用这个接口中的方法: 调用的方法是doSome-->在方法开始前打印系统当前时间,以及在最后打印一句话 调用的方法是doOther-->就正常输出
1、在开始和结束要输出的两句话(进行一个简单封装)
1 import java.text.SimpleDateFormat; 2 import java.util.Date; 3 4 /** 5 * @author zhangzhixi 6 */ 7 public class Utils { 8 public static void currentTime() { 9 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); 10 String showTime = sdf.format(new Date()); 11 System.out.println("当前系统时间为:" + showTime); 12 } 13 14 public static void executeTransaction(){ 15 System.out.println("事务执行结束"); 16 } 17 }
2、业务接口:
1 public interface UserService { 2 void doSome(); 3 void doOther(); 4 }
3、业务接口的实现类:
1 public class UserServiceImpl implements UserService { 2 @Override 3 public void doSome() { 4 System.out.println("doSome方法执行!~"); 5 } 6 7 @Override 8 public void doOther() { 9 System.out.println("doOther方法执行!~"); 10 } 11 }
4、创建调用处理程序类
1 package com.zhixi.invaction; 2 3 import com.zhixi.service.UserService; 4 import com.zhixi.util.Utils; 5 6 import java.lang.reflect.InvocationHandler; 7 import java.lang.reflect.Method; 8 import java.lang.reflect.Proxy; 9 10 /** 11 * @author zhangzhixi 12 */ 13 public class MyInvocation implements InvocationHandler { 14 15 /** 16 * 被代理的接口 17 */ 18 UserService userService; 19 20 public void setUserService(UserService userService) { 21 this.userService = userService; 22 } 23 24 public Object getProxy() { 25 // 生成得到代理类 26 return Proxy.newProxyInstance(this.getClass().getClassLoader(), userService.getClass().getInterfaces(), this); 27 } 28 29 30 /** 31 * @param proxy 代理对象 32 * @param method 代理的方法对象 33 * @param args 方法调用时参数 34 */ 35 @Override 36 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 37 Object invoke = null; 38 39 // 调用了doSome就执行这段业务 40 if ("doSome".equals(method.getName())) { 41 // 增加的业务 42 Utils.currentTime(); 43 44 /** 45 * userService: 被代理的类 46 * args: 参数 47 */ 48 invoke = method.invoke(userService, args); 49 50 // 增加的业务 51 Utils.executeTransaction(); 52 } else { 53 //说明调用了doOther 54 invoke = method.invoke(userService, args); 55 } 56 return invoke; 57 } 58 }
5、测试类:
1 public class MyTest { 2 public static void main(String[] args) { 3 // 创建目标对象 4 UserService userService= new UserServiceImpl(); 5 // 代理对象【不存在】 6 MyInvocation invocation = new MyInvocation(); 7 // 设置要代理的对象 8 invocation.setUserService(userService); 9 // 生成代理 10 UserService service = (UserService) invocation.getProxy(); 11 // 调用对象的业务方法 12 service.doSome(); 13 System.out.println("==============="); 14 service.doOther(); 15 } 16 }
6、测试结果:
当前系统时间为:2021年01月07日 21:56:41 doSome方法执行!~ 事务执行结束 =============== doOther方法执行!~