spring怎么用动态代理
-
要使用动态代理来使用Spring框架,首先需要了解什么是动态代理。动态代理是一种设计模式,通过在运行时创建和实现接口的代理类来完成方法的拦截和增强。在Spring框架中,动态代理经常用于实现AOP(面向切面编程)功能。
在Spring中,使用动态代理可以通过两种方式实现:JDK动态代理和CGLIB动态代理。
- JDK动态代理
JDK动态代理是基于接口进行代理的,所以被代理的类必须实现至少一个接口。实现JDK动态代理的步骤如下:
1.1 创建一个InvocationHandler接口的实现类,该类需要重写invoke方法。在invoke方法中实现业务逻辑的增强。
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: " + method.getName()); // 调用原始方法 Object result = method.invoke(target, args); // 在调用原始方法之后可以实现一些额外的逻辑 System.out.println("After method: " + method.getName()); return result; } }1.2 使用Proxy类的newProxyInstance方法创建代理对象。
public class Main { public static void main(String[] args) { UserService userService = new UserServiceImpl(); InvocationHandler handler = new MyInvocationHandler(userService); UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), handler); proxy.addUser("Tom"); } }- CGLIB动态代理
CGLIB动态代理是通过继承来实现代理的,所以被代理的类不能是final类。实现CGLIB动态代理的步骤如下:
2.1 创建一个MethodInterceptor接口的实现类,该类需要重写intercept方法。在intercept方法中实现业务逻辑的增强。
public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在调用原始方法之前可以实现一些额外的逻辑 System.out.println("Before method: " + method.getName()); // 调用原始方法 Object result = proxy.invokeSuper(obj, args); // 在调用原始方法之后可以实现一些额外的逻辑 System.out.println("After method: " + method.getName()); return result; } }2.2 使用Enhancer类创建代理对象。
public class Main { public static void main(String[] args) { UserService userService = new UserServiceImpl(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(userService.getClass()); enhancer.setCallback(new MyMethodInterceptor()); UserService proxy = (UserService) enhancer.create(); proxy.addUser("Tom"); } }以上是使用动态代理来使用Spring框架的基本步骤。在实际开发中,我们可以将代理逻辑封装成一个通用的类,然后使用Spring的配置文件来配置代理。通过动态代理,我们可以实现日志记录、事务管理等切面功能,提高代码的可维护性和灵活性。
1年前 - JDK动态代理
-
动态代理是Spring框架中非常常用的一种技术,可以在运行时生成代理对象,用于对目标对象进行增强或拦截。在Spring中,有两种常见的动态代理方式:JDK动态代理和CGLIB动态代理。下面是关于Spring如何使用动态代理的步骤和方法:
- 接口定义:首先,需要定义一个接口,该接口定义了目标对象的方法。
public interface UserService { void addUser(User user); void deleteUser(String userId); }- 目标对象实现:然后,创建一个类来实现上述接口,并实现其中的方法。
public class UserServiceImpl implements UserService { @Override public void addUser(User user) { // 添加用户的具体逻辑 } @Override public void deleteUser(String userId) { // 删除用户的具体逻辑 } }- 增强逻辑实现:如果需要在目标对象的方法执行前后加入一些额外的逻辑,可以创建一个实现了Advice接口的增强类,并在其中实现相应的前置和后置逻辑。
public class LogAdvice implements MethodBeforeAdvice, AfterReturningAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { // 在方法执行前执行的逻辑,比如打印日志 System.out.println("Before method: " + method.getName()); } @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { // 在方法执行后执行的逻辑,比如打印日志 System.out.println("After method: " + method.getName()); } }- 创建代理对象:使用Spring框架的ProxyFactoryBean或ProxyFactory类来创建代理对象。ProxyFactoryBean适用于基于接口的代理,而ProxyFactory适用于基于类的代理。
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); proxyFactoryBean.setTarget(new UserServiceImpl()); // 设置目标对象 proxyFactoryBean.setInterfaces(UserService.class); // 设置代理接口 proxyFactoryBean.setInterceptorNames("logAdvice"); // 设置增强逻辑 UserService userService = (UserService) proxyFactoryBean.getObject(); // 创建代理对象- 使用代理对象:可以像使用普通的目标对象一样使用代理对象,Spring会自动调用增强逻辑。
userService.addUser(user); // 调用代理对象的方法 userService.deleteUser(userId); // 调用代理对象的方法使用动态代理,可以对目标对象的方法进行拦截、增强、日志记录等操作,而不需要修改目标对象的源代码,提供了更好的灵活性和可扩展性。
1年前 -
Spring框架使用动态代理主要有两种方式:JDK动态代理和CGLIB动态代理。下面分别对这两种方式进行详细的介绍。
一、JDK动态代理
JDK动态代理是Java提供的一种动态代理技术,它能够在运行时动态地生成代理类和代理对象。JDK动态代理只能代理接口,不支持代理类。下面是使用JDK动态代理的步骤:- 首先需要定义一个接口,该接口是被代理对象需要实现的接口。例如,定义一个UserService接口:
public interface UserService { void addUser(String username, String password); void deleteUser(String username); void updateUser(String username, String password); }- 定义一个实现了InvocationHandler接口的类,该类为代理对象的调用处理器。例如,定义一个UserServiceInvocationHandler类:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; 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("Before method:" + method.getName()); // 调用目标方法 Object result = method.invoke(target, args); // 在调用目标方法后执行一些操作 System.out.println("After method:" + method.getName()); return result; } }- 在Spring配置文件中配置代理对象,并将该代理对象注入到需要使用的地方。例如,配置一个UserService代理对象:
<bean id="userServiceTarget" class="com.example.UserServiceImpl"/> <bean id="userServiceProxy" class="java.lang.reflect.Proxy" factory-method="newProxyInstance"> <constructor-arg value="com.example.UserService"/> <constructor-arg> <list> <value>com.example.UserServiceInvocationHandler</value> </list> </constructor-arg> </bean>- 使用代理对象进行方法调用。例如,通过userServiceProxy调用UserService的方法:
userServiceProxy.addUser("admin", "123456"); userServiceProxy.deleteUser("admin"); userServiceProxy.updateUser("admin", "654321");二、CGLIB动态代理
CGLIB(Code Generation Library)是一个基于ASM(一个高性能字节码操作库)的代码生成库,它能够在运行时动态地生成代理类和代理对象。相比于JDK动态代理,CGLIB动态代理支持代理类和代理接口。下面是使用CGLIB动态代理的步骤:- 添加CGLIB相关依赖。在项目的pom.xml(Maven项目)或build.gradle(Gradle项目)文件中添加以下依赖:
Maven:
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>Gradle:
compile 'cglib:cglib:3.3.0'- 定义一个类作为被代理对象,该类不需要实现接口。例如,定义一个UserServiceImpl类:
public class UserServiceImpl { public void addUser(String username, String password) { System.out.println("Add user: " + username); } public void deleteUser(String username) { System.out.println("Delete user: " + username); } public void updateUser(String username, String password) { System.out.println("Update user: " + username); } }- 定义一个实现了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 obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在调用目标方法前执行一些操作 System.out.println("Before method:" + method.getName()); // 调用目标方法 Object result = proxy.invokeSuper(obj, args); // 在调用目标方法后执行一些操作 System.out.println("After method:" + method.getName()); return result; } }- 创建Enhancer对象,并设置被代理类和方法拦截器。例如,创建一个UserService代理对象:
Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new UserServiceMethodInterceptor()); UserServiceImpl userServiceProxy = (UserServiceImpl) enhancer.create();- 使用代理对象进行方法调用。例如,通过userServiceProxy调用UserService的方法:
userServiceProxy.addUser("admin", "123456"); userServiceProxy.deleteUser("admin"); userServiceProxy.updateUser("admin", "654321");以上就是使用Spring框架实现动态代理的方法和操作流程。通过JDK动态代理和CGLIB动态代理,我们可以在不修改原始类的情况下实现对方法的增强和拦截处理。
1年前