Java设计模式==》动态代理模式原理+实践(JDK动态代理+CGLIB动态代理)

一、静态代理:
如果代理类在程序运行前就已经决定,那么这种代理方式被称为静态代理


好比如厂家通过微商代理来销售产品给客户这也就是代理
客户无法直接接触厂家而是通过微商代理来拿到产品的
这样做的好处:
  • 可以隐藏委托类的实现
  • 实现了客户和委托类的解耦,并且还能在不修改委托类的情况下做一些额外的处理
这就好比如说微商代理针对的客户群体是使用微信的客户
但是,这样做的前提是必须要在程序运行之前写好代理类
代码实现:委托类和代理类实现同一个接口或者继承相同的父类,然后可以在代理类中进行一些额外的处理
二、动态代理:
生成一个代理对象来代理真实对象,从而控制真实对象的访问

好比客户通过商务来对软件工程师进行需求修改。。。
优点:
  • 可以隐藏调用者的实现
  • 可以实现调用者与真实对象的解耦,在不修改代理对象的情况下
能够做一些额外的处理

所以代理必须分为两部:
  • 代理对象和真实对象之间建立代理关系
  • 真实对象实现代理对象的的代理逻辑方法
三、Java中的动态代理有: JDK、CGLIB 、ASM、Javassist
1、JDK动态代理(JDK自带)
使用JDK自带的Proxy类动态生成代理对象
依赖于java.lang.reflect.*包必须借助一个接口才能创建
由java内部的反射机制来实现的

代理对象逻辑
package me.ls.example;
//import java.lang.reflect.*
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//
public class JdkProxyExample implements InvocationHandler {
// 真实对象
private Object target = null;

/**
* 1.绑定代理对象和真实对象的代理关系
*
* @param 真实对象
* @return 代理对象
*/
public Object bind(Object target) {
// 保存真实对象
this.target = target;
// 生成代理对象
// proxy 代理的意思
// newProxyInstance创建代理对象
// 参数:
// 1.类加载器
// 2.把生成的代理对象下挂在真实对象下
// 3.自定义实现方法逻辑(invoke())的代理类
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}

/**
* 代理逻辑方法
*
* @param proxy
* 代理对象
* @param method
* 当前调度的方法
* @param args
* 调度方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调度真实对象之前的服务"); //使用反射在目标对象上调用方法并传入参数
Object obj = method.invoke(target, args);//相当于调用sayHello方法
System.out.println("在调度真实对象之后的服务");
return obj;
}

}

public interface Hello {
public void sayHello();
}


public class HelloImpl implements Hello {

@Override
public void sayHello() {
System.out.println("Hello Word! ===》JdkProxyExample invocationHandler Proxy java.lang.reflect.*");
}

}


import org.junit.jupiter.api.Test;

import me.ls.example.JdkProxyExample;
import me.ls.pojo.Hello;
import me.ls.pojo.HelloImpl;

class ExampleTest {

@Test
void JdkProxyTest() {
JdkProxyExample example=new JdkProxyExample();
//绑定关系并获取代理对象
//此时会自动进入invoke方法
Hello hello = (Hello) example.bind(new HelloImpl());
hello.sayHello();
}

}
关键词: JdkProxyExample(jdk动态代理例子)
invocationHandler(代理逻辑实现类需要实现此接口)
Proxy(动态代理)
java.lang.reflect.*(jdk动态代理依赖此包)
2、CGLIB动态代理(需要依赖第三方包)
底层使用ASM( C++中的一个关键字,用于在C++源码中内嵌汇编语言 )在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
cglib继承被代理的类,重写方法,织入通知,动态生成字节码并运行,因为是继承所以final类是没有办法动态代理的
不需要接口,只需要一个非抽象类就能实现动态代理。就好比下面这个HelloService要实现动态代理
与jdk动态代理相似都是使用getPrex·y方法生成代理对象,制定代理的逻辑类,而代理逻辑类都要实现一个接口的一个方法,而这个方法都是代理对象的逻辑方法,可以控制真实对象的方法。

public class HelloService {
public void sayHello() {
System.out.println("HelloWorld");

}
}

package me.ls.example;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibPrexyExample implements MethodInterceptor{
//生成代理对象
public Object getProxy(Class cls) {
//CGLIB enhancer增强类对象
Enhancer enhancer=new Enhancer();
//设置增强类的父类类型
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象,要求必须实现MethodInterceptor接口
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
System.out.println("调用真实对象前");
//CGLIB反射调用真实对象方法
Object result = proxy.invokeSuper(object, objects);
System.out.println("调用真实对象后");
return result;
}
}
@Test
void testCGLIBPrexy() {
//得到代理类对象
CglibPrexyExample cglibProxyExample=new CglibPrexyExample();
//通过代理类对象的getProxy方法获取代理对象
HelloService helloService= (HelloService) cglibProxyExample.getProxy(HelloService.class);
helloService.sayHello();
}

猜你喜欢

转载自blog.csdn.net/qq_35597614/article/details/80719847
今日推荐