Java动态代理
动态代理
实现方式一,JDK动态代理
public class Main {
public static void main(String[] args) {
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
Hello hello = (Hello) myInvocationHandler.newProxy(new HelloWorld());
hello.morning("lin");
}
}
// 目标接口
public interface Hello {
void morning(String name);
}
// 目标类
public class HelloWorld implements Hello {
@Override
public void morning(String name) {
System.out.println("Good Moning,"+name);
}
}
// 代理类;方法调用会被转发到该类的invoke()方法。
class MyInvocationHandler implements InvocationHandler{
// 目标代理对象,本例中的HelloWorld的实例
private Object targetObject;
// 构造代理对象
public Object newProxy(Object targetObject){
this.targetObject = targetObject;
return Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(), //
targetObject.getClass().getInterfaces(),
this
);
}
//利用反射,在原逻辑上进行增强
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行之前");
Object invoke = method.invoke(targetObject, args);
System.out.println("代理执行之后");
return invoke;
}
}
//打印结果:
代理开始之前
Good Moning,lin
代理开始之后
调用过程中的堆栈信息:
实现方式二,CGLIB动态代理
CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。 首先导入maven依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
因为没有实现接口该类无法使用JDK代理,通过CGLIB代理实现如下:
- 首先实现一个MethodInterceptor,方法调用会被转发到该类的intercept()方法。
- 然后在需要使用HelloJava的时候,通过CGLIB动态代理获取代理对象。
// 目标类
public class HelloJava {
public void hello(String name){
System.out.println("hello,"+name);
}
}
// 代理类
class MyMethodInterceptor implements MethodInterceptor{
// 进行增强
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理执行之前");
Object res = methodProxy.invokeSuper(o, args);
System.out.println("代理执行之后");
}
}
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloJava.class);
enhancer.setCallback(new MyMethodInterceptor());
// 通过enhancer创建HelloJava实例
HelloJava helloJava = (HelloJava) enhancer.create();
helloJava.hello("lin");
}
}
// 结果输出:
代理执行之前
hello,lin
代理执行之后
调用过程中的堆栈信息:
总结动态代理对象
动态代理是JDK在运行期动态使用反射机制创建class字节码并加载的过程,通过动态代理,我们可以在对象创建前后进行增强,或者对象方法调用前后进行增强,在Spring中借助该技术实现了AOP。