spring的动态代理是如何实现的
时间: 2024-06-07 13:11:44 浏览: 15
Spring的动态代理是基于Java的反射机制实现的。当我们使用Spring的AOP功能时,Spring会根据我们配置的切面和通知信息,在运行时动态地创建代理对象。代理对象会拦截目标对象的方法调用,执行相应的通知逻辑,然后再将控制权交给目标对象继续执行。这个过程中,Spring使用了JDK动态代理和CGLIB动态代理两种方式。
JDK动态代理是基于接口实现的代理,它要求目标对象必须实现至少一个接口。JDK动态代理通过Proxy类和InvocationHandler接口来实现,我们只需要编写一个实现InvocationHandler接口的代理类,然后让Proxy类动态生成代理对象即可。
CGLIB动态代理则是基于继承实现的代理,它不要求目标对象实现接口。CGLIB动态代理通过Enhancer类来实现,我们只需要编写一个继承自目标对象的子类,并重写需要增强的方法即可。
Spring会根据目标对象是否实现接口来选择使用JDK动态代理还是CGLIB动态代理,具体实现细节可以查看Spring的源代码。
相关问题
spring 动态代理如何实现的
Spring 动态代理是通过 JDK 动态代理或者 CGLIB 动态代理来实现的,具体根据被代理的类是否实现了接口来选择使用哪种方式。
JDK 动态代理是通过反射机制来生成一个实现被代理接口的代理类,代理类在调用方法时会委托给 InvocationHandler 实现类来处理。因为 JDK 动态代理是基于接口来实现的,所以被代理类必须实现一个或多个接口。
CGLIB 动态代理是通过继承被代理类,生成一个子类来实现的。代理类在调用方法时会覆盖父类的方法,通过 MethodInterceptor 接口来处理。CGLIB 动态代理可以代理没有实现接口的类。
Spring 在运行时根据被代理对象的接口或者父类来判断使用哪种方式来生成代理类。在使用 Spring AOP 时,如果被代理的对象实现了接口,则使用 JDK 动态代理;否则使用 CGLIB 动态代理。
Spring 动态代理实现
Spring动态代理是通过JDK动态代理和CGLIB动态代理两种方式来实现的。
1. JDK动态代理
JDK动态代理是利用Java反射机制在运行时创建一个实现某一接口的代理类对象。在Spring中,当一个目标类实现了至少一个接口时,默认采用JDK动态代理。JDK动态代理只能代理实现了接口的类,而不能代理没有实现接口的类。
示例代码:
```
public interface UserService {
void addUser();
}
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("add user");
}
}
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke method...");
Object result = method.invoke(target, args);
System.out.println("after invoke method...");
return result;
}
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandler invocationHandler = new MyInvocationHandler(userService);
UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(), invocationHandler);
proxy.addUser();
}
```
2. CGLIB动态代理
CGLIB动态代理是通过继承目标类,生成目标类的子类来实现代理。在Spring中,当一个目标类没有实现任何接口时,采用CGLIB动态代理。CGLIB动态代理需要依赖于CGLIB库,可以在运行时动态生成代理类字节码,并加载到JVM中。
示例代码:
```
public class UserService {
public void addUser() {
System.out.println("add user");
}
}
public class MyMethodInterceptor implements MethodInterceptor {
private Object target;
public MyMethodInterceptor(Object target) {
this.target = target;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before invoke method...");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after invoke method...");
return result;
}
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new MyMethodInterceptor(new UserService()));
UserService userService = (UserService) enhancer.create();
userService.addUser();
}
```
相关推荐
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)