1. Proxy

1.1. Proxy 模式优缺点

  1. 代理模式的主要优点

代理模式在客户端与目标客户之间起到一个中介作用和保护目标对象的作用
代理对象可以扩展目标对象的功能
代理模式可以将客户端与目标对象分离,在一定程度上降低了系统的耦合度

  1. 代理模式带来的主要问题

在客户端和目标对象之间增加一个代理对象,会造成请求速度变慢
增加了系统的复杂度

1.2. 动态代理原理

1.2.1. 创建动态代理类

  1. Proxy proxyClass = Proxy.getProxyClass(ClassLoader,需要代理的目标对象接口)

动态代理类的解释

  1. Proxy类是public, final和非abstract的
  2. Proxy类继承了java.lang.reflect.Proxy
  3. Proxy类的权限定名是未指定的

如果Proxy类实现了非public的接口,它将被定义在这个接口相同的包中,否则proxy类的包是未定义
Proxy类实现了它创建时指定的接口(集合),以相同的顺序

  1. 将Proxy类传递给函数Proxy.isProxyClass,它将放回true

1.2.2. 实例化Proxy代理对象

所有Proxy类都有一个public的构造函数,它接收一个InvocationHandler实例为参数。
它可以通过反射获得该构造函数,并创建Proxy实例

  1. // 通过反射获取动态代理类的构造函数
  2. Constructor constructor = proxyClass.getConstructor(new Class[]{InvocationHandler.class})
  3. // 创建动态代理实例
  4. constructor.newInstance(new Object[]{new MyInvocatoinHandler()}) // MyInvocationHandler类会实现java.lang.reflect.InvocationHandler接口,该类实现动态代理的逻辑

Proxy代理实例

  1. 每一个Proxy实例都有一个关联的InvocationHandler对象,实现了java.lang.reflect.InvocationHandler接口,该类实现动态代理的逻辑。调用Proxy实例的方法时,Proxy实例将转发给调用InvocationHandler对象的invoke()方法,相当于调用了InvocationHandler接口实现类invoke()方法实现的逻辑
  2. InvocatonHandler对象的invoke方法接收三个参数

the proxy instance:代理类的实例
a java.lang.reflect.Method object identifying the method that was invoked:
an array of type Object containing the arguments:
创建动态代理类并实例化

  1. // 一步实现创建代理类和实例化代理类
  2. Proxy.newProxyInstance(类加载器,需要代理的目标对象接口,invocationHandler)

1.3. 总结

  1. 创建动态代理类后,实例化动态代理类时通过动态代理类的构造函数传入InvocationHandler接口的实现类。
  2. 动态代理类中的目标接口的实现方法中会调用InvocationHandler接口的invoke方法,既就是调用InvocationHandler接口实现类的invoke方法
  3. 这样就可以在InvocationHandler接口的实现类中的invoke方法中编写代理逻辑,实现动态代理。

image.png

3. CGLIB

3.1. 创建代理对象

  1. package my.tngd.proxy.cglib;
  2. import net.bytebuddy.build.ToStringPlugin;
  3. import org.springframework.cglib.core.DebuggingClassWriter;
  4. import org.springframework.cglib.proxy.Enhancer;
  5. public class Client {
  6. public static void main(String[] args) {
  7. // 指定代理对象生成在本地磁盘路径,方便反编译分析
  8. System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\cglib");
  9. // 通过CGLIB 创建代理对象过程
  10. Enhancer enhancer = new Enhancer();
  11. enhancer.setSuperclass(HelloCglibService.class);
  12. enhancer.setCallback(new MyMethodInterceptor());
  13. HelloCglibService service = (HelloCglibService) enhancer.create();
  14. service.sayHello();
  15. }
  16. }

3.2. 拦截器

  1. package my.tngd.proxy.cglib;
  2. import org.springframework.cglib.proxy.MethodInterceptor;
  3. import org.springframework.cglib.proxy.MethodProxy;
  4. import java.lang.reflect.Method;
  5. public class MyMethodInterceptor implements MethodInterceptor {
  6. @Override
  7. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  8. System.out.println("====================前置通知====================" + method);
  9. Object result = methodProxy.invokeSuper(o, objects);
  10. System.out.println("====================后置通知====================" + method);
  11. return result;
  12. }
  13. }

3.3. 被代理类

  1. package my.tngd.proxy.cglib;
  2. public class HelloCglibService {
  3. public HelloCglibService() {
  4. System.out.println("HelloCglibService 构造函数");
  5. }
  6. final public String sayOther(String name) {
  7. System.out.println("HelloService:sayOthers>>" + name);
  8. return name;
  9. }
  10. public void sayHello() {
  11. System.out.println("HelloService:sayHello");
  12. }
  13. }