JDK动态代理
静态代理其实就是事先写好代理类,可以手工编写也可以使用工具生成,但它的缺点是每个业务类都要对应一个代理类,特别不灵活也不方便,于是就有了动态代理。
动态代理的常见使用场景有 RPC 框架的封装、AOP(面向切面编程)的实现、JDBC 的连接等。
Spring 框架中同时使用了两种动态代理 JDK Proxy 和 CGLib,当 Bean 实现了接口时,Spring 就会使用 JDK Proxy,在没有实现接口时就会使用 CGLib,我们也可以在配置中指定强制使用 CGLib,只需要在 Spring 配置中添加 <aop:aspectj-autoproxy proxy-target-class="true"/>
即可。
创建接口
创建 CarService
接口:
interface CarService {
void running();
void stop();
}
创建接口实现类
创建 CarService
的实现类 BusCarServiceImpl
:
class BusCarServiceImpl implements CarService {
@Override
public void running() {
System.out.println("car running");
}
@Override
public void stop() {
System.out.println("car stop");
}
}
创建 JDK InvocationHandler 实现类
创建 JDKProxy
类实现 InvocationHandler
的 invoke
方法:
class JDKProxy<T> implements InvocationHandler {
/**
* 被代理的对象
*/
private T target;
public JDKProxy(T target) {
this.target = target;
}
/**
* 生成代理对象
*/
public T getProxyInstant() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行,被代理的方法:" + method.getName() + ",被代理的类:" + target.getClass().getSimpleName());
return method.invoke(target, args);
}
}
测试
public static void main(String[] args) {
// 获取代理对象
JDKProxy<CarService> jdkProxy = new JDKProxy<>(new BusCarServiceImpl());
CarService busCarServiceImpl = jdkProxy.getProxyInstant();
// 调用代理对象的方法
busCarServiceImpl.running();
busCarServiceImpl.stop();
}
运行结果:
代理执行,被代理的方法:running,被代理的类:BusCarServiceImpl
car running
代理执行,被代理的方法:stop,被代理的类:BusCarServiceImpl
car stop
CGlib动态代理
CGlib 动态代理相比于 JDK 动态代理的好处就是非接口方法也能实现代理。
引入 CGlib 依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
创建接口
创建接口实现类
创建 CarService
的实现类 BusCarServiceImpl
,其中 general 方法是非接口方法,用于体现 CGlib 动态代理与 JDK 动态代理的不同之处:
class BusCarServiceImpl implements CarService {
@Override
public void running() {
System.out.println("car running");
}
@Override
public void stop() {
System.out.println("car stop");
}
public void general() {
System.out.println("general");
}
}
创建 CGlib MethodInterceptor 实现类
创建 CGLibProxy
类实现 MethodInterceptor
的 intercept
方法:
class CGLibProxy<T> implements MethodInterceptor {
/**
* 被代理的对象
*/
private T target;
public CGLibProxy(T target) {
this.target = target;
}
/**
* 生成代理对象
*/
public T getProxyInstant() {
Enhancer enhancer = new Enhancer();
// 设置父类为实例类
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return (T) enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理执行,被代理的方法:" + method.getName() + ",被代理的类:" + target.getClass().getSimpleName());
return methodProxy.invokeSuper(o, objects);
}
}
测试
public static void main(String[] args) {
// 获取代理对象
CGLibProxy<BusCarServiceImpl> cgLibProxy = new CGLibProxy<>(new BusCarServiceImpl());
BusCarServiceImpl carService = cgLibProxy.getProxyInstant();
// 调用代理对象的方法
carService.running();
carService.stop();
// 非接口方法也能被代理
carService.general();
}
运行结果:
代理执行,被代理的方法:running,被代理的类:BusCarServiceImpl
car running
代理执行,被代理的方法:stop,被代理的类:BusCarServiceImpl
car stop
代理执行,被代理的方法:general,被代理的类:BusCarServiceImpl
general