代理模式是Java常见的设计模式之一。 为什么要采用这种间接的形式来调用对象呢? 代理模式可以有 2 种实现的方式: 现有 User 实体类: UserDaoImpl 实现类: 需求:通过 静态代理、装饰者、动态代理模式分别 ① 自定义一个代理类(增强类)实现和被代理类(被增强类)相同的接口 测试静态代理类; 运行结果: 优点:不修改源码 ① 自定义一个装饰类(增强类)实现和被装饰类(被增强类)相同的接口 测试装饰者类: 运行结果: 优点:不修改源码 动态代理是通过反射来实现的,借助Java自带的 JDK提供的代理只能针对接口做代理,有更强大的代理 步骤:—— 优化:③④可合并为实现了对应接口 InvocationHandler 接口的 invoke 方法参数解释: 匿名内部类直接测试: 优点:静态代理、装饰者、动态代理
代理模式是指不直接调用实际对象,而是通过调用代理,来间接的调用实际的对象。
场景①:不想直接访问
实际的对象;
场景②:对实际的对象的访问存在困难
;
场景③:有需求需要将封装对象访问/操作的成员方法进行逻辑增强,而不修改原方法
;
在现实生活中,这种情形非常的常见,比如请一个律师代理来打官司。
一种是静态代理
,另一种是各大框架都喜欢的动态代理
。
还有一种类似静态代理的装饰者模式
。public class User { private int id; // 编号属性 id private String name; // 姓名属性 name public User() { } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + ''' + '}'; } }
DAO封装数据访问思想:用来封装对实体类 User 类的访问/操作。
UserDao 接口:public interface UserDao { void add(); void delete(); void update(); void select(); }
public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("add"); } @Override public void delete() { System.out.println("delete"); } @Override public void update() { System.out.println("update"); } @Override public void select() { System.out.println("select"); } }
增强 add() 方法的逻辑功能
。1. 静态代理设计模式
1.1 静态代理 – 实现步骤
② 在代理类中声明被代理类的对象
③ 在代理类的方法中使用被代理类调用方法1.2 静态代理 – 逻辑图 & 源码示例
代理类(该类 UserDaoProxy)、被代理类(UserDaoImpl):/** * 静态代理设计模式 */ // 1.实现和被代理类相同的接口 public class UserDaoProxy implements UserDao { // 2.在代理类中声明被代理类的引用 private UserDao userDao; public UserDaoProxy() { userDao = new UserDaoImpl(); } // 3.在代理类的方法中使用被代理类调用方法 @Override public void add() { System.out.println("权限校验"); userDao.add(); System.out.println("日志记录"); } @Override public void delete() { userDao.delete(); } @Override public void update() { userDao.update(); } @Override public void select() { userDao.select(); } }
public class TestProxy { public static void main(String[] args) { // 测试静态代理模式 UserDaoProxy userDaoProxy = new UserDaoProxy(); userDaoProxy.add(); userDaoProxy.delete(); }
1.3 静态代理 – 优缺
增强
被代理类的功能,可以控制
被代理类的对象
缺点:必须要重写被代理类接口的所有的方法,耦合性高
2. 装饰者设计模式 – 类似静态代理
2.1 装饰者模式 – 实现步骤
② 在装饰类中声明被装饰类的引用
③ 在装饰类的方法中使用被装饰类调用方法2.2 装饰者模式 – 逻辑图 & 源码示例
装饰类(该类 UserDaoWrapper)、被装饰类(UserDaoImpl):/** * 装饰设计模式 */ // 1.实现和被装饰类相同的接口 public class UserDaoWrapper implements UserDao { // 2.在装饰类中声明被装饰类的引用 private UserDao userDao; public UserDaoWrapper() { } public UserDaoWrapper(UserDao userDao) { this.userDao = userDao; } // 3.在装饰类的方法中使用被装饰类调用方法 @Override public void add() { System.out.println("权限校验"); userDao.add(); System.out.println("日志记录"); } @Override public void delete() { userDao.delete(); } @Override public void update() { userDao.update(); } @Override public void select() { userDao.select(); } }
public class TestProxy { public static void main(String[] args) { // 测试装饰设计模式 UserDaoWrapper userDaoWrapper = new UserDaoWrapper(new UserDaoImpl()); userDaoWrapper.add(); userDaoWrapper.delete(); }
2.3 装饰者模式 – 优缺
增强
被代理类的功能,无法控制
被代理类的对象
缺点:必须要重写被代理类接口的所有的方法,耦合性高
3. 动态代理设计模式【最优】
java.lang.reflect.Proxy
通过固定的规则生成。
动态代理本质就是通过反射
来生成的一个代理。
在Java中 java.lang.reflect 包下提供了一个 Proxy 类
和 InvocationHandler 接口
,通过使用这个类和接口就可以生成动态代理对象,Proxy类中的方法创建动态代理对象。cglib
:
一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。3.1 动态代理设计模式 – 实现步骤
基于接口的方法增强
① 编写一个代理类的接口
② 实现一个真正的代理类,实现该接口
③ 创建一个动态的代理类,实现 InvocationHandler 接口
,并重写该 invoke()
方法
④ 在测试类中调用 Proxy.newProxyInstance()
方法生成动态代理对象匿名内部类
替代。
即 在调用该动态代理对象的成员方法时,是 invoke 增强的方法执行。3.2 动态代理设计模式 – 逻辑图 & 源码示例
Proxy.newProxyInstance() 方法的参数解释: /* * 通过反射来实现的动态代理核心方法 * @loader: 被代理类对应的类加载器 * @interfaces: 被代理类所实现的所有接口 * @h: 一个用以增强代理类的处理器 * @return Object对象 */ @CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
/** * 在代理实例上处理方法调用,并返回结果 * @param proxy 代理类的实例 * @param method 被代理类的原方法 * @param args 被代理类的原方法的实际参数 * @return Object对象 */ @Override public Object invoke(Object proxy, Method method, Object[] args);
public class TestProxy { public static void main(String[] args) { UserDao userDao = new UserDaoImpl(); //动态代理设计模式:匿名内部类对象 UserDao p = (UserDao) Proxy.newProxyInstance( userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), //Lambda表达式,等价于 new InvocationHandler(){ invoke(){...} } (proxy, method, argss) -> { String methodName = method.getName(); Object result; //方法名比较:只增强指定的需要增强的方法 if ("add".equals(methodName)) { System.out.println("权限校验"); result = method.invoke(userDao, argss); System.out.println("日志记录"); } else { result = method.invoke(userDao, argss); } return result; }); p.add(); p.delete(); }
3.3 动态代理设计模式 – 优缺
不需要重写接口中的所有方法,耦合度更低
。
缺点:没有,动态代理就是这么任性,这条gai最靓的仔本仔!
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算