spring中aop使用什么代理
-
Spring中AOP使用的是JDK动态代理和CGLIB代理两种方式。
- JDK动态代理:
JDK动态代理是通过Java的反射机制来实现的,要求目标对象必须实现一个接口。在Spring中,通过配置一个实现了InvocationHandler接口的代理对象来实现AOP功能。当目标对象的方法被调用时,代理对象会通过反射调用InvocationHandler的invoke方法,在该方法中可以实现对目标对象方法的增强逻辑。
使用JDK动态代理的步骤如下:
- 定义一个实现InvocationHandler接口的代理类;
- 创建目标对象的实例;
- 使用Proxy类的newProxyInstance方法创建代理对象;
- 调用代理对象的方法。
JDK动态代理的优点是可以在运行时动态地创建代理对象,无需修改目标对象的源代码,缺点是只能代理实现了接口的目标对象。
- CGLIB代理:
CGLIB是一个强大的基于字节码的动态代理库,它可以在运行时动态生成目标类的子类,从而实现代理的功能。相比于JDK动态代理,CGLIB代理不要求目标对象实现接口,可以代理目标对象的所有方法。
使用CGLIB代理的步骤如下:
- 引入CGLIB的依赖;
- 定义一个实现MethodInterceptor接口的代理类;
- 创建Enhancer对象,设置父类和拦截器;
- 调用Enhancer对象的create方法创建代理对象;
- 调用代理对象的方法。
CGLIB代理的优点是可以代理非接口的目标对象,缺点是生成代理类的过程比较耗时,会影响应用的启动速度。
总结来说,Spring中AOP使用的是JDK动态代理和CGLIB代理两种方式,其中JDK动态代理适用于代理实现了接口的目标对象,而CGLIB代理适用于代理非接口的目标对象。
1年前 - JDK动态代理:
-
在Spring中,AOP使用两种类型的代理:基于JDK的动态代理和基于CGLlib的动态代理。
-
JDK动态代理:
JDK动态代理是基于接口的代理。当目标对象实现了接口时,Spring将使用JDK动态代理生成目标对象的代理类。JDK动态代理是基于Java反射机制实现的。它利用了Java的动态代理API来创建代理对象。JDK动态代理使用的接口是java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy。 -
CGLib动态代理:
CGLib动态代理是基于继承的代理。CGLib通过生成目标对象的子类来创建代理对象,从而达到代理的目的。CGLib不需要目标对象实现接口,因此可以代理那些没有实现接口的目标对象。CGLib动态代理使用的类是net.sf.cglib.proxy.MethodInterceptor和net.sf.cglib.proxy.Enhancer。 -
JDK动态代理和CGLib动态代理的区别:
JDK动态代理可以代理实现了接口的类,而CGLib动态代理可以代理任意的类,包括没有实现接口的类。另外,JDK动态代理是基于接口的,所以目标对象必须实现接口;而CGLib动态代理是基于继承的,所以目标对象不需要实现接口。 -
如何选择代理方式:
一般情况下,如果目标对象实现了接口,推荐使用JDK动态代理;如果目标对象没有实现接口,或者需要代理的是一个类而不是一个接口,可以使用CGLib动态代理。当然,Spring会根据情况自动选择合适的代理方式。 -
动态代理的应用场景:
动态代理通常用于实现方法的增强。在Spring中,AOP就是通过动态代理实现的。动态代理可以在目标方法执行前后、异常时等切入额外的逻辑,比如日志记录、事务管理等。动态代理还常常用于实现代理工厂、缓存代理等功能。
1年前 -
-
在Spring AOP中,使用了两种代理来实现AOP的功能:JDK动态代理和CGLIB代理。下面将详细介绍这两种代理的使用方法和实现原理。
JDK动态代理:
JDK动态代理是基于接口的代理,它的核心是Java提供的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。JDK动态代理只能对实现了接口的类生成代理,原理是通过在运行时生成一个代理类,该代理类通过实现目标对象的接口,并将方法的调用委托给InvocationHandler来处理。使用JDK动态代理的步骤如下:
- 定义一个InvocationHandler。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; 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 method call"); Object result = method.invoke(target, args); // 调用目标对象的方法 // 在代理对象调用方法后可以添加一些逻辑 System.out.println("After method call"); return result; } }- 创建代理对象。
import java.lang.reflect.Proxy; public class ProxyFactory { public static Object getProxy(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new MyInvocationHandler(target)); } }其中,Proxy.newProxyInstance()方法用于创建代理对象,它接受三个参数:ClassLoader,目标对象实现的接口数组,和InvocationHandler对象。
- 使用代理对象调用方法。
public interface UserService { void addUser(String username, String password); } public class UserServiceImpl implements UserService { @Override public void addUser(String username, String password) { System.out.println("Add user: " + username); } } public class Main() { public static void main(String[] args) { UserService userService = new UserServiceImpl(); UserService proxy = (UserService) ProxyFactory.getProxy(userService); proxy.addUser("John", "123456"); } }输出结果:
Before method call Add user: John After method callCGLIB代理:
CGLIB代理是基于继承的代理,它不要求目标对象实现接口,原理是通过继承目标对象,并使用Enhancer类生成目标对象的子类,子类中增加了增强的代码。使用CGLIB代理的步骤如下:
- 添加CGLIB的依赖。
在Maven项目中,需要添加以下依赖:
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>- 定义一个MethodInterceptor。
import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在代理对象调用方法前可以添加一些逻辑 System.out.println("Before method call"); Object result = proxy.invokeSuper(obj, args); // 调用目标对象的方法 // 在代理对象调用方法后可以添加一些逻辑 System.out.println("After method call"); return result; } }- 创建代理对象。
import net.sf.cglib.proxy.Enhancer; public class ProxyFactory { public static Object getProxy(Object target) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); // 设置父类,即目标对象的类 enhancer.setCallback(new MyMethodInterceptor()); // 设置回调对象 return enhancer.create(); } }- 使用代理对象调用方法。
public class UserService { public void addUser(String username, String password) { System.out.println("Add user: " + username); } } public class Main() { public static void main(String[] args) { UserService userService = new UserService(); UserService proxy = (UserService) ProxyFactory.getProxy(userService); proxy.addUser("John", "123456"); } }输出结果:
Before method call Add user: John After method call综上所述,Spring AOP使用JDK动态代理和CGLIB代理来实现AOP的功能。JDK动态代理适用于接口代理,CGLIB代理适用于类代理。在选择代理时,需要根据目标对象是否实现接口来决定使用哪种代理;同时,CGLIB代理由于是基于继承的代理,可能会对final类和final方法无效。
1年前