spring如何创建代理对象
-
Spring创建代理对象的方式有两种:JDK动态代理和CGLIB动态代理。
-
JDK动态代理:JDK动态代理是基于接口的代理,它使用Proxy类和InvocationHandler接口来创建代理对象。
首先,定义一个实现InvocationHandler接口的类,该类中需要实现invoke方法,该方法会在代理对象的方法被调用时被调用。
其次,通过Proxy类的newProxyInstance方法创建代理对象。该方法接受三个参数:ClassLoader,用于加载代理类;Class[],被代理类的接口列表;InvocationHandler,用于处理代理对象方法调用的逻辑。
示例代码如下:
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 { // 增加代理逻辑 // ... Object result = method.invoke(target, args); // 增加代理逻辑 // ... return result; } } // 创建代理对象 MyInterface realObject = new MyInterfaceImpl(); MyInvocationHandler handler = new MyInvocationHandler(realObject); MyInterface proxyObject = (MyInterface) Proxy.newProxyInstance( realObject.getClass().getClassLoader(), realObject.getClass().getInterfaces(), handler); -
CGLIB动态代理:CGLIB动态代理是基于类的代理,它通过继承被代理类并重写其方法来实现代理。
首先,引入cglib和asm库依赖。
其次,定义一个实现MethodInterceptor接口的类,该类中需要实现intercept方法,该方法会在代理对象的方法被调用时被调用。在intercept方法中,可以通过MethodProxy来调用原始方法。
然后,通过Enhancer类的create方法创建代理对象。create方法接受两个参数:Class,被代理类;Callback,用于处理代理对象方法调用的逻辑。
示例代码如下:
public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 增加代理逻辑 // ... Object result = proxy.invokeSuper(obj, args); // 增加代理逻辑 // ... return result; } } // 创建代理对象 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyClass.class); enhancer.setCallback(new MyMethodInterceptor()); MyClass proxyObject = (MyClass) enhancer.create();
通过以上两种方式,我们可以使用Spring创建代理对象来实现一些横切逻辑,例如事务管理、日志记录等。根据实际需求选择适合的代理方式。
1年前 -
-
Spring提供了多种方式来创建代理对象,下面是其中几种常见的方式:
-
基于接口的代理:Spring使用JDK动态代理机制来基于接口创建代理对象。当目标对象实现了至少一个接口时,Spring会使用JDK动态代理来创建代理对象。代理对象会实现目标对象所实现的所有接口,并重写接口中的方法,从而实现代理功能。这种方式需要在配置文件中使用aop:config标签进行配置。
-
基于类的代理:当目标对象没有实现任何接口时,Spring使用CGLIB代理来创建代理对象。CGLIB是基于字节码的代码生成库,它通过生成目标对象的子类来实现代理功能。代理对象继承目标对象,重写目标对象中的方法,并在方法前后添加增强逻辑。这种方式不需要目标对象实现接口,只需要在配置文件中使用aop:config标签进行配置。
-
使用注解方式:Spring提供了基于注解的方式来创建代理对象。通过在目标对象的方法上添加注解,告诉Spring要对该方法进行增强操作。Spring会根据注解的配置自动创建代理对象,并在目标方法执行前后执行增强逻辑。常见的注解方式有@Aspect和@Around等。
-
使用编程方式:Spring还提供了编程方式来创建代理对象。通过编写Java代码,手动创建代理对象,并指定代理对象的目标对象、增强逻辑等。这种方式需要在代码中使用ProxyFactory类或者Proxy类来创建代理对象,并进行相关的配置。
-
使用模板方式:Spring还提供了模板方式来创建代理对象。通过借助Spring框架中的代理模板类,如JdbcTemplate和RestTemplate等,可以方便地创建代理对象并进行相关操作。这种方式适用于特定的场景,如数据库访问、远程调用等。
1年前 -
-
Spring框架提供了多种方式来创建代理对象。本文将介绍两种常见的方式:基于接口的代理和基于类的代理。
一、基于接口的代理
基于接口的代理是通过JDK动态代理来实现的。JDK动态代理是Java提供的一种动态创建代理对象的机制,需要目标类实现一个或多个接口。使用基于接口的代理可以按照以下步骤进行:
- 创建目标类的接口
首先,需要创建一个接口,定义目标类的方法。
public interface UserService { void addUser(User user); void deleteUser(User user); User getUser(String username); }- 创建目标类
然后,创建一个实现了目标类接口的类。
public class UserServiceImpl implements UserService { public void addUser(User user) { // 添加用户的逻辑 } public void deleteUser(User user) { // 删除用户的逻辑 } public User getUser(String username) { // 获取用户的逻辑 } }- 创建代理类
接下来,创建一个代理类,实现InvocationHandler接口,并重写invoke方法。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class UserServiceProxy implements InvocationHandler { private Object target; public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } 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; } }- 使用代理对象
最后,可以通过代理类创建代理对象并调用目标方法。
public class Main { public static void main(String[] args) { UserService userService = new UserServiceImpl(); UserService proxy = (UserService) new UserServiceProxy().bind(userService); proxy.addUser(new User("Alice")); proxy.deleteUser(new User("Bob")); User user = proxy.getUser("Alice"); } }二、基于类的代理
基于类的代理是通过CGLib库来实现的。CGLib是一个强大的,高性能的代码生成库,可以在运行时动态生成目标类的子类。使用基于类的代理可以按照以下步骤进行:
- 导入CGLib库
首先,需要在项目中导入CGLib的相关依赖。
Maven:
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>Gradle:
implementation 'cglib:cglib:3.3.0'- 创建目标类
与基于接口的代理不同,不需要创建接口。直接创建目标类即可。
public class UserService { public void addUser(User user) { // 添加用户的逻辑 } public void deleteUser(User user) { // 删除用户的逻辑 } public User getUser(String username) { // 获取用户的逻辑 } }- 创建代理类
接下来,创建一个代理类,继承MethodInterceptor类,并重写intercept方法。
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class UserServiceProxy implements MethodInterceptor { private Object target; public Object bind(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在目标方法执行前的逻辑 System.out.println("Before method: " + method.getName()); // 执行目标方法 Object result = proxy.invoke(target, args); // 在目标方法执行后的逻辑 System.out.println("After method: " + method.getName()); return result; } }- 使用代理对象
最后,创建代理对象并调用目标方法。
public class Main { public static void main(String[] args) { UserService userService = new UserService(); UserService proxy = (UserService) new UserServiceProxy().bind(userService); proxy.addUser(new User("Alice")); proxy.deleteUser(new User("Bob")); User user = proxy.getUser("Alice"); } }总结:
通过以上两种方式,可以创建基于接口或基于类的代理对象。基于接口的代理适用于目标类实现了接口的情况,而基于类的代理适用于目标类没有实现接口的情况。这些代理对象可以在目标方法执行前后添加额外的逻辑,实现对目标方法的拦截和增强。1年前 - 创建目标类的接口