在Java中 动态代理主要有两种实现方式
1.CGlib, 一个第三方代码生成类库, 运行时在内存中生成一个子类来实现动态代理, 通过字节码操作技术来实现动态代理, 在通过方法拦截机制对目标方法进行拦截或增强( 例如Servlet的filter ,分页插件等), 实现对接口的代理,配合AOP框架的使用
2.JDK动态代理: java.reflect中的Proxy和InvocationHandler接口
如果实现了InvocationHandler这个接口定义了一个方法invoke()
, 当通过代理对象调用接口方法时,实际上会触发到invoke()
方法的调用。
Proxy类提供了创建动态代理对象的静态方法 newProxyInstance()方法返回来一个实现了指定接口的代理对象,当这个代理对象的方法被调用时,会转发到对应InvocationHandler.invoke()
方法中处理。
静态代理和动态代理的区别
最大的区别就是静态代理在编译期间就会被确定的, 而动态代理则是在运行期间被确定的, 反射就是动态代理的其中一种实现方式
总结
Java中 的动态代理, 基本是我们都会用到, 但其实感知不会那么明显, 主要的应用层面是SSM那一套比较熟悉, 例如AOP Servlter中的过滤器(MVC中的拦截器其实关系并不大,他更像是一种中间件),.mybatis中的分页插件, 或者说是我们针对分页参数的初始化操作, 事务,日志,权限,都离不开动态代理的身影子
JDK动态代理片段
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个接口,我们的代理对象将实现此接口
interface MyService {
void doSomething(String arg);
int calculate(int a, int b);
}
// 目标对象,实现了MyService接口
class RealService implements MyService {
@Override
public void doSomething(String arg) {
System.out.println("RealService: Doing something with " + arg);
}
@Override
public int calculate(int a, int b) {
return a + b;
}
}
// 实现InvocationHandler接口,用于定义代理对象的行为
class LoggingHandler implements InvocationHandler {
private final MyService target; // 被代理的目标对象
public LoggingHandler(MyService target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Method '" + method.getName() + "' is being called.");
// 在方法调用前添加日志或其他逻辑
System.out.println("Arguments: " + Arrays.toString(args));
// 调用目标对象的实际方法
Object result = method.invoke(target, args);
// 在方法调用后添加日志或其他逻辑
System.out.println("Method returned: " + result);
return result;
}
}
public class DynamicProxyDemo {
public static void main(String[] args) {
// 创建实际的服务对象
MyService realService = new RealService();
// 创建InvocationHandler实例,传入目标对象
InvocationHandler loggingHandler = new LoggingHandler(realService);
// 使用Proxy.newProxyInstance创建代理对象,需要提供:
// 1. 目标对象的类加载器
// 2. 目标对象实现的所有接口
// 3. 实现InvocationHandler接口的实例(定义代理行为)
MyService proxy = (MyService) Proxy.newProxyInstance(
MyService.class.getClassLoader(),
new Class<?>[]{MyService.class},
loggingHandler
);
// 现在可以像操作普通MyService对象一样操作代理对象
proxy.doSomething("example argument");
int sum = proxy.calculate(10, 20);
System.out.println("Sum: " + sum);
}
}
Cglib动态代理片段
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
// 目标类,无需实现接口
class TargetClass {
public void doSomething(String arg) {
System.out.println("TargetClass: Doing something with " + arg);
}
public int calculate(int a, int b) {
return a + b;
}
}
// 实现MethodInterceptor接口,用于定义代理对象的行为
class LoggingInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Method '" + method.getName() + "' is being called on " + obj.getClass().getSimpleName());
// 在方法调用前添加日志或其他逻辑
System.out.println("Arguments: " + Arrays.toString(args));
// 调用目标对象的实际方法
Object result = proxy.invokeSuper(obj, args);
// 在方法调用后添加日志或其他逻辑
System.out.println("Method returned: " + result);
return result;
}
}
public class CGLibProxyDemo {
public static void main(String[] args) {
// 创建实际的目标对象
TargetClass target = new TargetClass();
// 创建Enhancer对象,指定要代理的类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetClass.class);
// 设置回调方法,即代理逻辑
enhancer.setCallback(new LoggingInterceptor());
// 生成并返回代理对象
TargetClass proxy = (TargetClass) enhancer.create();
// 现在可以像操作普通TargetClass对象一样操作代理对象
proxy.doSomething("example argument");
int sum = proxy.calculate(10, 20);
System.out.println("Sum: " + sum);
}
}