spring如何实现动态代理
-
Spring框架提供了两种方式实现动态代理:JDK动态代理和CGLIB动态代理。
- JDK动态代理:
JDK动态代理是基于接口的代理模式,要求被代理的类实现一个或多个接口。JDK动态代理通过反射机制在运行时创建代理对象,可以动态地将方法调用转发到被代理对象上。
首先,定义一个InvocationHandler接口的实现类,该类用于定义代理类的方法调用处理逻辑。在该类的invoke方法中,可以对方法进行增强、过滤或转发。
然后,在服务类中调用Proxy.newProxyInstance方法创建代理对象。该方法接受三个参数:类加载器、被代理类实现的接口列表和InvocationHandler实例。
最后,通过代理对象调用方法时,会自动执行代理逻辑。
- CGLIB动态代理:
CGLIB动态代理是基于继承的代理模式,不要求被代理的类实现接口。CGLIB动态代理通过创建目标类的子类来实现代理。
首先,引入CGLIB相关的依赖。然后定义一个方法拦截器类,该类用于定义代理类的方法调用处理逻辑。
接着,使用Enhancer类创建代理对象。该类通过设置父类、方法拦截器和回调类型来创建代理对象。
最后,通过代理对象调用方法时,会自动执行代理逻辑。
总结:
JDK动态代理适用于要求被代理类实现接口的场景,而CGLIB动态代理适用于不要求被代理类实现接口的场景。在Spring中,通过配置文件或注解即可使用这两种动态代理方式。1年前 - JDK动态代理:
-
Spring框架提供了两种实现动态代理的方式:JDK动态代理和CGLib动态代理。接下来将分别介绍这两种方式的实现方法。
- JDK动态代理
JDK动态代理是基于接口的代理,它通过在运行时创建一个实现指定接口的代理类来实现代理功能。JDK动态代理的核心类是java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler。具体步骤如下:
- 创建一个InvocationHandler实现类,重写invoke方法,在invoke方法中通过反射调用目标对象的方法。
- 使用Proxy的静态方法newProxyInstance()创建代理对象,参数包括ClassLoader、代理接口数组和InvocationHandler。
- 通过代理对象调用目标方法。
- CGLib动态代理
CGLib动态代理是基于字节码的代理,它通过继承目标类来实现代理功能。CGLib动态代理的核心类是net.sf.cglib.proxy.Enhancer。具体步骤如下:
- 创建一个MethodInterceptor实现类,重写intercept方法,在intercept方法中通过cglib库中的MethodProxy类调用目标对象的方法。
- 使用Enhancer的create()方法创建代理对象,参数包括目标类和MethodInterceptor。
- 通过代理对象调用目标方法。
-
配置动态代理
无论是使用JDK动态代理还是CGLib动态代理,都需要将代理对象配置到Spring的配置文件中。在Spring配置文件中,需要指定目标对象和代理对象的关系,以及代理方式是JDK动态代理还是CGLib动态代理。 -
使用动态代理
配置完成后,就可以在代码中使用动态代理了。可以通过注入代理对象来调用目标对象的方法,并在方法调用前后进行增强操作。 -
动态代理的应用场景
动态代理在Spring框架中有着广泛的应用。它可以用来实现事务管理、日志记录、性能监控等功能。通过动态代理,可以将这些横切关注点与业务逻辑解耦,使得代码更加清晰和易于维护。
1年前 - JDK动态代理
-
Spring框架通过使用动态代理技术来实现许多功能,包括事务管理、AOP(面向切面编程)和远程方法调用等。Spring提供了两种主要的动态代理技术:JDK动态代理和CGLIB动态代理。
- JDK动态代理
JDK动态代理基于Java的反射机制,只能对接口进行代理。JDK动态代理是通过接口的实例来生成代理对象,并且代理对象实现了接口中定义的方法。具体步骤如下:
- 创建一个InvocationHandler接口的实现类,该类负责实现代理对象的具体操作逻辑。
- 通过Proxy类的newProxyInstance方法创建代理对象。该方法接收三个参数:ClassLoader,用于指定代理对象的类加载器;Class[],用于指定代理对象实现的接口;InvocationHandler,用于指定代理对象的具体操作逻辑。
- 使用代理对象进行方法调用。
以下是一个示例代码:
public interface UserDao { void save(); } public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("Saving data..."); } } 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 execution..."); Object result = method.invoke(target, args); System.out.println("After method execution..."); return result; } } public class Main { public static void main(String[] args) { UserDao userDao = new UserDaoImpl(); InvocationHandler handler = new MyInvocationHandler(userDao); UserDao proxy = (UserDao) Proxy.newProxyInstance( userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), handler ); proxy.save(); } }代理对象执行save()方法时,会先执行MyInvocationHandler类中的invoke()方法,并在调用目标方法前后输出日志。
- CGLIB动态代理
CGLIB动态代理是基于字节码生成技术实现的,可以对类进行代理。CGLIB会继承目标类,并重写其方法来实现代理。具体步骤如下:
- 引入CGLIB库到项目中。
- 创建一个MethodInterceptor接口的实现类,该类负责实现代理对象的具体操作逻辑。
- 创建Enhancer对象,并设置父类以及回调函数。
- 使用代理对象进行方法调用。
以下是一个示例代码:
public class UserDao { public void save() { System.out.println("Saving data..."); } } public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Before method execution..."); Object result = proxy.invokeSuper(obj, args); System.out.println("After method execution..."); return result; } } public class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserDao.class); enhancer.setCallback(new MyMethodInterceptor()); UserDao proxy = (UserDao) enhancer.create(); proxy.save(); } }代理对象执行save()方法时,会先执行MyMethodInterceptor类中的intercept()方法,并在调用目标方法前后输出日志。
总结:
Spring框架通过使用JDK动态代理和CGLIB动态代理技术来实现动态代理。JDK动态代理只能对接口进行代理,基于Java的反射机制实现;CGLIB动态代理可以对类进行代理,基于字节码生成技术实现。开发者可以选择适合自己需求的动态代理技术来实现各种功能。
1年前