静态代理
- 我们在不修改业务的情况下想要给它增加一些功能,这就需要使用代理模式。
- 我们不会在原有业务上直接修改,为了避免修改导致程序不可逆转的破坏。
- 三种角色:抽象角色-接口、真实角色-实现类和代理角色-代理类。
- 真实角色和代理角色继承的是同一个抽象角色接口!
业务接口类
负责抽象出业务需要的功能。
//抽象业务 public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
业务的实现类
public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("增加了一个用户"); } @Override public void delete() { System.out.println("删除了一个用户"); } @Override public void update() { System.out.println("修改了一个用户"); } @Override public void query() { System.out.println("查询了一个用户"); } }
代理类
假如我们现在要给业务增加一个新的功能-输出日志功能,我们需要通过一个代理类来实现 ,而不是直接在旧业务上修改代码。
我们增加一个 log 方法(拓展功能),我们需要一个 set 方法来使代理能够通过旧的实现类调用旧的业务。
//代理实现增删改查 public class UserServiceProxy implements UserService{ UserServiceImpl userService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } @Override public void add() { log("add"); userService.add(); } @Override public void delete() { log("delete"); userService.delete(); } @Override public void update() { log("update"); userService.update(); } @Override public void query() { log("query"); userService.query(); } public void log(String message){ System.out.println("使用了" + message + "方法"); } }
测试
这样我们的只需要给代理设置旧业务的实现类就实现了业务的功能扩展。
public class Client { public static void main(String[] args) { UserServiceImpl service = new UserServiceImpl(); UserServiceProxy proxy = new UserServiceProxy(); proxy.setUserService(service); proxy.add(); } }
动态代理
- 动态代理个静态代理角色一样(抽象角色-接口、真实角色-实现类和代理角色-代理类)
- 动态代理的代理类是通过反射动态生成的!
- 动态代理按照实现可以分我:基于接口的 和 基于类的动态代理。
- 基于接口:JDK 动态代理
- 基于类:cglib
- 需要了解两个类:Proxy:代理、InvocationHandler:调用处理程序。
- 一个动态代理类就是一个接口!
- 一个动态代理类可以代理多个真实角色类,只需要继承同一个业务接口即可。
- 使用动态代理可以大大减少代码量!因为它使用了反射!
Proxy:
Proxy 一共只有4个方法:
InvocationHandler:
InvocationHandler是一个接口!
InvocationHandler 整个类里只有一个方法:invoke方法。
动态代理的实现
抽象角色
//抽象业务 public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
真实角色
public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("增加了一个用户"); } @Override public void delete() { System.out.println("删除了一个用户"); } @Override public void update() { System.out.println("修改了一个用户"); } @Override public void query() { System.out.println("查询了一个用户"); } }
代理角色
使用 Object 作为抽象角色,这样这一个代理类就可以当做工具类来给任何真实角色进行功能扩展!
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //代理处理程序 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Object target; public void setUserService(Object target) { this.target = target; } //生成并得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } //处理代理实例,调用抽象接口的方法,并返回结果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //动态代理的本质就是使用反射机制实现! fun1(); log(method.getName()); Object result = method.invoke(target, args); fun2(); return result; } public void fun1(){ System.out.println("扩展功能1"); } public void fun2(){ System.out.println("扩展功能2"); } public void log(String message){ System.out.println("执行了" + message + "方法"); } }
测试
public class Client { public static void main(String[] args) { //真实角色 UserServiceImpl userService = new UserServiceImpl(); //代理角色 ProxyInvocationHandler handler = new ProxyInvocationHandler(); //设置要代理的真实对象 handler.setUserService(userService); //动态生成代理类 UserService proxy = (UserService) handler.getProxy(); proxy.add(); proxy.delete(); } }
输出结果:
扩展功能1 执行了add方法 增加了一个用户 扩展功能2 扩展功能1 执行了delete方法 删除了一个用户 扩展功能2