不属于网站架构,域名的定义,wordpress英文别名,网上网站建设教程一:动态代理和静态代理的区别
静态代理#xff1a;了解设计模式中的代理模式的童鞋应该都知道#xff0c;如果想要生成代理类#xff0c;需要让代理类和被代理类实现同一个接口#xff0c;并且在代理类中添加被代理类的引用#xff0c;代理类方法实现中添加代理逻辑…一:动态代理和静态代理的区别
静态代理了解设计模式中的代理模式的童鞋应该都知道如果想要生成代理类需要让代理类和被代理类实现同一个接口并且在代理类中添加被代理类的引用代理类方法实现中添加代理逻辑并决定是否调用被代理类方法这种通过硬编码的方式指定代理类与被代理类的方式叫静态代理。可以明显看出静态代理类与被代理类是强耦合的如果要代理100个类你就得写100个代理类 动态代理其实动态代理与静态代理的本质一样最终程序运行时都需要生成一个代理对象实例通过它来完成相关增强以及业务逻辑只不过静态代理需要硬编码的方式指定而动态代理则是以动态方式生成代理(有编译时操作字节码生成的方式、运行时通过反射、字节码生成的方式)。动态生成的好处很明显代理逻辑与业务逻辑是互相独立的没有耦合代理1个类或100个类要做的事情没有任何区别
说到耦合必须把AOP拿来说道说道传统面向对象思想中如果想要实现功能复用要么继承、要么引用无论哪种方式对代码都有一定的侵入性耦合无可避免侵入性啥意思简单来说如果你想要用它增强你程序的功能你必须改动你的程序代码那它就具有侵入性。如果只有一点两点需要增强还好说如果大量的功能点需要被增强工作量就会很大代码也不太优雅。想象一下如果你对外公开了一系列的接口现在领导说了接口要加权限控制。在哪加最笨的当然就是写个程序验证的逻辑然后每个接口都拿来调用一遍。这也正是面向对象思想的短板在要为程序新增一些通用功能时只能通过耦合的方式才能进行。AOP正是为此而生AOP旨在通过一种无耦合的方式来为程序带来增强。而动态代理就是AOP实现方式中的一种
二:动态代理相关的类
Proxy:生成动态代理的实例 InvocationHandler: 每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时方法调用将被编码并分派到其调用处理程序的invoke方法。(invoke方法可以通过反射加载被代理的类的方法)
三代码实现
1接口
package com.wyj.demo03;public interface UserService {void deleteUser();void addUser();void updateUser();void selectUser();
}
2实现类
package com.wyj.demo03;import com.wyj.demo03.UserService;public class UserServiceImp implements UserService {Overridepublic void deleteUser() {System.out.println(删除一个用户);}Overridepublic void addUser() {System.out.println(增加一个用户);}Overridepublic void updateUser() {System.out.println(修改一个用户);}Overridepublic void selectUser() {System.out.println(查询一个用户);}
}
3生成动态代理类的程序
package com.wyj.demo03;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 setTarget(Object target) {this.target target;}//生成得到代理类这里我们返回的是一个接口 也就是被代理的类 所实现的接口public Object getProxy() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}/**** param proxy :被代理的对象* param method:被代理的对象的方法* param args :被代理的对象的参数* return* throws Throwable*/Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {log(method.getName());Object invoke method.invoke(target, args);//在反射中通过 方法名.invoke(类名);传统方法中 类名.方法名();return invoke;}//增加需求 打印日志public void log(String msg) {System.out.println(调用了msg);}
}
其中的参数解析 类加载机制: 首先我们要了解一下类的加载机制在每创建一个Java类时都会生产一个.class文件在内存中对应也会生成一个class对象来表示该类的类型信息我们可以用.class来获取这个类的所有信息也可以通过getClass方法来读取这个类的所有信息比如getClass().getInterfaces获取类的接口信息等。在Java类加载时要通过一个类加载器classloader来将生成的Java类加载到JVM中才能执行。理解了类的加载机制后我们再看代码中的newProxyInstance方法在这个方法中我们将被代理对象传进来后.
在Proxy.newProxyInstance方法中共有三个参数 1、target.getClass().getClassLoader()目标对象通过getClass方法获取类的所有信息后调用getClassLoader()方法来获取类加载器。获取类加载器后可以通过这个类型的加载器在程序运行时将生成的代理类加载到JVM即Java虚拟机中以便运行时需要 2、target.getClass().getInterfaces()获取被代理类的所有接口信息以便于生成的代理类可以具有代理类接口中的所有方法。 3、this我们使用动态代理是为了更好的扩展比如在方法之前做什么之后做什么等操作。这个时候这些公共的操作可以统一交给代理类去做。这个时候需要调用实现了InvocationHandler 类的一个回调方法。由于自身实现了这个方法所以将this传递过去。 也就是在这个ProxyInvocationHandler 类自身中实现一些需求的方法
4:实现过程
package com.wyj.demo03;public class Client {public static void main(String[] args) {//真实角色UserServiceImp serviceImp new UserServiceImp();//代理角色不存在ProxyInvocationHandler handler new ProxyInvocationHandler();//设置被代理的对象handler.setTarget(serviceImp);//得到代理类对象(这个是我们返回是一个接口,我们的被代理类是实现的一个接口)UserService proxy (UserService) handler.getProxy();proxy.deleteUser();}
}
实现过程的解析: 代理类是在运行时创建的实现指定的接口列表称为代理接口的类 。 代理实例(proxy)是代理类的一个实例。 每个代理实例(proxy)都有一个关联的调用处理程序对象(handler)它实现接口InvocationHandler 。 通过其代理接口之一的代理实例上的方法调用将被分派到实例调用处理程序的invoke方法传递代理实例标识调用方法的java.lang.reflect.Method对象以及包含参数的类型为Object的数组。 调用处理程序适当地处理编码方法调用并且返回的结果将作为方法在代理实例上调用的结果返回。