JDK代理 & CGLib
date
Jul 26, 2021
slug
JavaProxy
status
Published
tags
Java Proxy
summary
JDK静态代理、JDK动态代理、CGLib代理的学习笔记
type
Post
Language
介绍
个人认为 Java 中的代理和
Nginx 的代理从意思上说都差不多,都是把目标转发到代理对象上,隐藏原始目标或对目标进行拦截或增强准备
public interface helloInterface{
public void say();
}public class hello implements helloInterface{
@Override
public void say(){
System.out.println("hello");
}
}JDK静态代理
从 Java 语言特性上实现业务层面上的代理
public class helloStationaryProxy implements helloInterface{
private Hello hello;
@Override
public void say(){
if (hello == null) {
hello = new Hello();
}
hello.say();
}
}
HelloStaticProxy helloStaticProxy = new HelloStaticProxy();
helloStaticProxy.say();JDK动态代理
代理类实现
InvocationHandler 接口,通过 Proxy 类的静态方法 newProxyInstance 传入代理类的类加载器和被代理对象的接口动态的创建代理类实现public class HelloDynamicProxy implements InvocationHandler {
private Object subject;
public HelloDynamicProxy(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(subject, args);
return null;
}
}Hello hello = new Hello();
InvocationHandler handler = new HelloDynamicProxy(hello);
// 传入handler的类加载器和被代理类的接口,以此动态创建代理类
HelloInterface helloInterface = (HelloInterface) Proxy.newProxyInstance(
handler.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
handler
);
helloInterface.say();CGLib代理
底层把方法全部放入数组,通过数组索引直接调用方法
public class HelloMethodInterceptor implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object object = methodProxy.invokeSuper(o, objects);
return object;
}
}Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Hello.class);
enhancer.setCallback(new HelloMethodInterceptor());
HelloInterface helloInterface1 = (HelloInterface) enhancer.create();
helloInterface1.say();Spring AOP实现
- Spring 默认使用
JDK动态代理实现AOP,SpringBoot 使用CGLib
- 如果被代理的类实现了接口就使用
JDK动态代理,如果被代理的类没有实现接口就使用CGLib
- 使用
CGLib实现 AOP,被代理的类方法为final就无法实现代理,被代理类为final会报错