设计模式-2-代理模式
简介:对原有类的方法,增加控制或者完全替换
目的:在保持原有类不变的前提下,对其方法进行改动
总结:给方法增加拦截控制,类似前后置拦截器
注:被代理类必须实现一个接口,或者被代理类就是接口
分类:1-静态代理 2-动态代理
一,基础类
UserService.java
package com.design.proxy; public interface UserService { /** * 用户查询 * @param userId * @return */ User get(Long userId); }
UserServiceImpl.java
package com.design.proxy; public class UserServiceImpl implements UserService { @Override public User get(Long userId) { if(userId == null || User.userMap.size() == 0){ return null; } if(User.userMap.containsKey(userId)){ return User.userMap.get(userId); } return null; } }
二,静态代理
package com.design.proxy; /** * 代理模式 - 静态代理 * * 代理模式: * 在原有类的行为基础上,加入一些多出的行为,甚至完全替换原有的行为 * * 静态代理: * 静态代理采用的方式就是我们手动的将这些行为换进去,然后让编译器帮我们编译,同时也就将字节码在原有类的基础上加入一些其他的东西或者替换原有的东西,产生一个新的与原有类接口相同却行为不同的类型。 * * 总结: * 1,代理类一般要持有一个被代理的对象的引用。 * 2,对于我们不关心的方法,全部委托给被代理的对象处理。 * 3,自己处理我们关心的方法。 */ public class UserStaticProxy implements UserService{ //1-构造方法中强行传入一个被代理的对象的引用; 将我们不关心的方法,交给被代理的对象去处理; 将关心的直接进行处理 private UserService userService; public UserStaticProxy(UserService userService) { super(); this.userService = userService; } /** * 代理类要处理的方法 */ @Override public User get(Long userId) { System.out.println("使用静态代理模式处理UserService.get(Long userId)方法 start .... "); User user = userService.get(userId); System.out.println("使用静态代理模式处理UserService.get(Long userId)方法 end ..."); return user; } /** * 代理类不处理的方法使用强行传入的被代理类引用来处理 */ @Override public Long save(User user) { return userService.save(user); } }
Main
package com.design.b.proxy; public class MainTest { @SuppressWarnings("unused") private static UserService userService; public static void main(String[] args) { /** * 静态代理模式 */ userService = new UserServiceImpl(); //1-获取被代理对象 UserService userServiceProxy = new UserStaticProxy(userService); //2-将被代理对象通过构造函数强行传入代理类 User user = userServiceProxy.get(1001L); System.out.println("get result :" + user.toString()); } }
Result:
使用静态代理模式处理UserService.get(Long userId)方法 start .... UserStaticProxy --> get user =User [userId=1001, userName=杨文军, mobile=13003600001, idCard=330224196702265835] 使用静态代理模式处理UserService.get(Long userId)方法 end ...
三,动态代理
package com.design.b.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 代理模式 - 动态代理 * * 动态代理:是JDK自带功能,需要实现InvocationHandler接口,使用proxy静态方法产生代理类 */ public class DynamicProxy implements InvocationHandler{ //1-构造方法中强行传入一个被代理的对象的引用 private Object resource; public DynamicProxy(Object resource) { super(); this.resource = resource; } //2-定义要处理的被代理对象方法的操作 private void before(){ System.out.println("DynamicProxy --> before (UserService.update): 方法之前处理 ... ... "); } private void after(){ System.out.println("DynamicProxy --> after (UserService.update): 方法之后处理 ... ... "); } //3-通过invoke对被代理对象要处理的方法进行操作 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /** * 对UserService接口中的update方法做动态处理 */ //前置处理 if(UserService.class.isAssignableFrom(proxy.getClass()) && "update".equals(method.getName())){ before(); } Object result = method.invoke(resource, args); //后置处理 if(UserService.class.isAssignableFrom(proxy.getClass()) && "update".equals(method.getName())){ after(); } return result; } //4-获取被代理对象 public Object getProxy(){ return Proxy.newProxyInstance(getClass().getClassLoader(), resource.getClass().getInterfaces(), this); } }
Main:
package com.design.b.proxy; public class MainTest { @SuppressWarnings("unused") private static UserService userService; public static void main(String[] args) { /** * 动态代理模式 */ DynamicProxy dynamicProxy = new DynamicProxy(new UserServiceImpl()); UserService userServiceDynamicProxy = (UserService) dynamicProxy.getProxy(); User userUpd = new User(1001L, "杨文军2", "13003600001", "330224196702265835"); Boolean upd = userServiceDynamicProxy.update(userUpd); System.out.println("udpate result :" + upd.toString() + "; after :" + userServiceDynamicProxy.get(1001L).toString()); } }
Result:
DynamicProxy --> before (UserService.update): 方法之前处理 ... ... DynamicProxy --> after (UserService.update): 方法之后处理 ... ... udpate result :true; after :User [userId=1001, userName=杨文军2, mobile=13003600001, idCard=330224196702265835]