java代理模式有静态代理和动态代理两种实现方式
一、静态代理
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
优点:
可以在不修改目标对象的前提下扩展目标对象的功能。
缺点:
冗余:由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。
不易维护:一旦接口增加方法,目标对象与代理对象都要进行修改。
**静态代理的特点**
1、目标角色固定
2、在应用程序执行前就得到目标角色
3、代理对象会增强目标对象的行为
4、有可能存在多个代理 引起"类爆炸"(缺点)
二、动态代理
动态代理利用了 JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。
动态代理又被称为 JDK 代理或接口代理。静态代理与动态代理的区别主要在:
1、静态代理在编译时就已经实现,编译完成后代理类是一个实际的 class 文件
2、动态代理是在运行时动态生成的,即编译完成后没有实际的 class 文件,而是在运行时动态生成类字节码,并加载到 JVM 中
注意:动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。
JDK 中生成代理对象主要涉及两个类,第一个类为 java.lang.reflect.Proxy,通过静态方法 newProxyInstance 生成代理对象,第二个为 java.lang.reflect.InvocationHandler 接口,通过 invoke 方法对业务进行增强
**动态代理的特点**
1、目标对象不固定
2、在应用程序执行时动态创建目标对象
3、代理对象会增强目标对象的行为
三、代码实例
用代码模拟一下结婚和婚庆公司演示静态代理
// 定义一个接口结婚的接口 interface Mary{ void mary() ; } //每个人都要结婚 class You implements Mary{//真实角色 @Override public void mary() { System.out.println("要结婚了,很开心..."); } } //婚庆公司---代理角色 class WeddingCompany implements Mary{ //声明一个接口Mary类型变量 private Mary mary ; public WeddingCompany(Mary mary){ //形式参数是一个接口,需要接口实现类对象 this.mary = mary ; } @Override public void mary() { //代理角色需要帮助真实角色完成一件 "结婚这件事情" System.out.println("结婚之前,需要布置婚礼现场...."); mary.mary() ; System.out.println("结婚之后,给婚庆公司付尾款...."); } } public class StaticProxyDemo { public static void main(String[] args) { //没有使用静态代理之前 //接口多态或者是具体类new 具体类 Mary mary = new You() ; mary.mary() ; System.out.println("-----------------------------------------"); //使用静态代理 You you = new You() ; //创建代理角色 WeddingCompany weddingCompany = new WeddingCompany(you) ; weddingCompany.mary(); } }
输出结果:
要结婚了,很开心… ----------------------------------------- 结婚之前,需要布置婚礼现场… 要结婚了,很开心… 结婚之后,给婚庆公司付尾款…
用代码模拟一下结婚和婚庆公司演示动态代理
1、针对用户访问的数据接口
public interface UserDao { /** * 添加功能 */ void add() ; /** * 修改功能 */ void update() ; /** * 查询功能 */ void select() ; /** * 删除功能 */ void delete() ; }
2、针对用户数据访问接口的实现
public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("添加功能"); } @Override public void update() { System.out.println("修改功能") ; } @Override public void select() { System.out.println("查询功能"); } @Override public void delete() { System.out.println("删除功能"); } }
3、版本2:对业务方法 add,update,select.delete进行增强
public class UserDaoImpl2 implements UserDao { @Override public void add() { System.out.println("权限校验") ; System.out.println("执行添加功能"); System.out.println("产生日志文件"); } @Override public void update() { System.out.println("权限校验") ; System.out.println("执行修改功能"); System.out.println("产生日志文件"); } @Override public void select() { System.out.println("权限校验") ; System.out.println("执行查询功能"); System.out.println("产生日志文件"); } @Override public void delete() { System.out.println("权限校验") ; System.out.println("执行删除功能"); System.out.println("产生日志文件") ; } }
/*Proxy类下边的方法newProxyInstance * public static Object newProxyInstance(ClassLoader loader, 参数1:实现的接口的类加载器 * Class<?>[] interfaces, 参数2:基于接口的字节码文件对象数组 * InvocationHandler h) 参数3:是接口InvocationHandler :代理的处理程序 * throws IllegalArgumentException * 参数3是一个接口:自定一个类实现这个接口 * 重写这个接口中的invoke方法 * Object invoke(Object proxy,Method method,Object[] args)throws Throwable */
4、基于代理的处理程序
public class MyInvocation implements InvocationHandler { //要针对谁产生代理: ud UserDao ud = new UserDaoImpl() ; private Object target ; //因为代理角色可以是任意Java类型,所以用Object public MyInvocation(Object target){ this.target = target ; } //方法的返回值就是代理对象 @Override //就是我们的接口的方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验") ; //调用接口的列表自己的方法:update(),delete(),add(),select() //当前实例--->真实角色 Object obj = method.invoke(target, args); //代理角色产生 System.out.println("产生日志文件"); return obj; } }
5、测试类
public class JdkProxyDemo { public static void main(String[] args) { //接口多态:测试UserDao UserDao ud = new UserDaoImpl() ; //真实角色 //版本1:现在需要对功能增强,这个代码不合适! ud.add(); ud.update(); ud.select(); ud.delete(); System.out.println("----------------------------------"); UserDao ud2 = new UserDaoImpl2() ; ud2.add(); ud2.update(); ud2.select(); ud2.delete(); System.out.println("----------------Jdk动态代理------------------"); //前提示需要一个接口:UserDao MyInvocation handler = new MyInvocation(ud) ; // public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) UserDao proxyInstance = (UserDao) Proxy.newProxyInstance( ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), handler); proxyInstance.add(); proxyInstance.update(); proxyInstance.select(); proxyInstance.delete(); } }
结果:
添加功能 修改功能 查询功能 删除功能 ---------------------------------- 权限校验 执行添加功能 产生日志文件 权限校验 执行修改功能 产生日志文件 权限校验 执行查询功能 产生日志文件 权限校验 执行删除功能 产生日志文件 ----------------Jdk动态代理------------------ 权限校验 添加功能 产生日志文件 权限校验 修改功能 产生日志文件 权限校验 查询功能 产生日志文件 权限校验 删除功能 产生日志文件
参考:
https://blog.csdn.net/zjshuster/article/details/126439883
https://blog.csdn.net/longzorg_cn/article/details/129115728
https://blog.csdn.net/m0_67499084/article/details/124810718
标签:java,静态,System,接口,代理,println,public,out From: https://www.cnblogs.com/51python/p/17296362.html