静态代理和动态代理的区别
原理区别
- 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在。代理类和目标类实现相同的接口,代理类内部持有目标类的实例,通过构造函数传入,在代理类的方法中调用目标类的对应方法,同时可以在前后添加额外逻辑。
- 动态代理:在程序运行时,运用反射机制动态创建代理类的实例。JDK动态代理是基于接口实现,通过Proxy类的
newProxyInstance
方法创建代理对象,该方法接收类加载器、接口数组和InvocationHandler对象作为参数。InvocationHandler接口的实现类负责处理代理对象的方法调用,在invoke
方法中通过反射调用目标对象的方法并可添加额外逻辑。CGLIB动态代理是基于继承,为目标类创建一个子类,在子类中重写父类方法来实现代理功能。
使用场景区别
- 静态代理:适用于代理类和目标类关系固定,业务场景简单且代理类数量有限的情况。比如,在一些小型项目中,对特定的几个服务类进行简单的日志记录、权限验证等功能。
- 动态代理:适用于代理类和目标类关系不固定,需要根据不同情况动态创建代理的场景。例如,在大型框架中,如Spring AOP,需要对各种不同的业务对象进行切面逻辑处理,动态代理能够灵活地为不同对象创建代理。
实现过程区别
- 静态代理:需要手动编写代理类,实现与目标类相同的接口,在代理类的方法中调用目标类的方法,并添加额外逻辑。
- 动态代理:JDK动态代理通过Proxy类和InvocationHandler接口实现,无需手动编写代理类,只需要实现InvocationHandler接口的
invoke
方法;CGLIB动态代理通过继承目标类生成代理类,需要引入CGLIB库,通过Enhancer类来创建代理对象。
代码示例
静态代理示例
- 定义
UserService
接口
public interface UserService {
boolean login(String username, String password);
}
- 实现
UserServiceImpl
类
public class UserServiceImpl implements UserService {
@Override
public boolean login(String username, String password) {
System.out.println("用户 " + username + " 尝试登录,密码:" + password);
return "admin".equals(username) && "123456".equals(password);
}
}
- 创建静态代理类
UserServiceProxy
public class UserServiceProxy implements UserService {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
@Override
public boolean login(String username, String password) {
System.out.println("开始验证权限...");
boolean result = userService.login(username, password);
System.out.println("登录结果:" + result);
return result;
}
}
- 测试静态代理
public class StaticProxyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy(userService);
proxy.login("admin", "123456");
}
}
动态代理示例(JDK动态代理)
- 定义
UserService
接口和UserServiceImpl
类(同静态代理示例)
- 创建
InvocationHandler
实现类UserServiceInvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class UserServiceInvocationHandler implements InvocationHandler {
private Object target;
public UserServiceInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始验证权限...");
Object result = method.invoke(target, args);
System.out.println("登录结果:" + result);
return result;
}
public Object getProxy() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
- 测试JDK动态代理
public class JdkDynamicProxyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserServiceInvocationHandler handler = new UserServiceInvocationHandler(userService);
UserService proxy = (UserService) handler.getProxy();
proxy.login("admin", "123456");
}
}
动态代理示例(CGLIB动态代理)
- 引入CGLIB依赖(如果使用Maven,在pom.xml中添加如下依赖)
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
- 定义
UserService
接口和UserServiceImpl
类(同静态代理示例),但这里UserServiceImpl
不需要实现接口(CGLIB基于继承)
- 创建
MethodInterceptor
实现类UserServiceMethodInterceptor
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class UserServiceMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始验证权限...");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("登录结果:" + result);
return result;
}
}
- 测试CGLIB动态代理
import net.sf.cglib.proxy.Enhancer;
public class CglibDynamicProxyTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(new UserServiceMethodInterceptor());
UserServiceImpl proxy = (UserServiceImpl) enhancer.create();
proxy.login("admin", "123456");
}
}