动态代理有哪几种实现方式?
什么是动态代理?
动态代理是一种在运行时动态生成代理对象,并在代理对象上进行方法调用的编程技术。它主要用于在不修改原有代码基础上,增加或改变某些功能的执行流程。动态代理广泛应用于AOP(面向切面编程)、RPC(远程过程调用)、事务管理等领域。在Java中,主要有两种动态代理的实现方式:JDK动态代理和CGLIB动态代理。
JDK动态代理
定义:
JDK动态代理是基于接口的代理技术。它使用 java.lang.reflect.Proxy
代理类和
java.lang.reflect.InvocationHandler
接口来创建代理对象。当你调用代理对象的任何方法时,调用会被转发到InvocationHandler 的 invoke方法。你可以在这个invoke方法中定义拦截逻辑,比如前置处理、后置处理等。
你的类必须实现一个或多个接口,局限性只能代理接口方法
实现:
-
定义一个接口及其实现类。
-
创建一个实现了InvocationHandler接口的类,在该类的invoke方法中定义代理逻辑。
-
通过[Proxy.nevProxyInstance](//通过 Proxy.newProxyInstance 方法动态创建接口的代理对象
public static void main(String[] args) {
// 创建目标对象
HelloService target = new HelloServiceImpl();
// 创建调用处理器对象
HelloServiceHandler handler = new HelloServiceHandler(target);
// 创建代理对象
HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler); // 通过代理对象调用方法
proxyInstance.sayHello("World");
}
)方法动态创建接口的代理对象。
1.定义一个接口及其实现类
// 定义一个接口
public interface HelloService {
void sayHello(String name);
}
// 实现该接口的类
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello(String name) {
System.out.println("Hello, " + name);
}
}
2.创建一个实现了InvocationHandler接口的类
//创建一个实现 InvocationHandler 接口的类
public class HelloServiceHandler implements InvocationHandler {
//目标对象
private Object target;
public HelloServiceHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before sayHello");
// 执行目标对象的方法
Object result = method.invoke(target, args);
System.out.println("After sayHello");
return result;
}
}
3.通过 Proxy.newProxyInstance 方法动态创建接口的代理对象
//通过 Proxy.newProxyInstance 方法动态创建接口的代理对象
public static void main(String[] args) {
// 创建目标对象
HelloService target = new HelloServiceImpl();
// 创建调用处理器对象
HelloServiceHandler handler = new HelloServiceHandler(target);
// 创建代理对象
HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler);
// 通过代理对象调用方法
proxyInstance.sayHello("World");
}
Cglib动态代理
不需要接口,它是通过继承方式实现代理的
CGLIB底层通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不仅可以代理普通类的方法,还能代理那些没有接口的类的方法。
优点以及缺点:
- 优点:无需接口实现。在大量调用的场景下,其生成的代理对象在调用时性能比JDK动态代理高
- 缺点:对final方法无效,需添加额外的依赖。
实现:
- 创建一个被代理的类
- 创建一个继承
MethodInterceptor
的代理类,在intercept
方法中定义代理逻辑 - 使用
Enhancer
类创建被代理类的子类,并设置回调
1.创建一个被代理的类
//定义一个普通类
public class HelloService {
public void sayHello(String name) {
System.out.println("Hello, " + name);
}
}
2.创建一个继承MethodInterceptor
的代理类,在intercept
方法中定义代理逻辑
//创建一个继承 MethodInterceptor 的代理类 实现 intercept 方法
public class HelloServiceCglib implements MethodInterceptor {
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 设置回调
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before sayHello");
// 执行目标类的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("After sayHello");
return result;
}
}
3.实现
//实现
public static void main(String[] args) {
HelloService target = new HelloService();
HelloServiceCglib cglib = new HelloServiceCglib();
HelloService proxy = (HelloService) cglib.getInstance(target);
proxy.sayHello("World");
}
标签:target,Object,代理,接口,HelloService,动态,public
From: https://www.cnblogs.com/wnbzw/p/18580613