Spring的代理如何实现
-
Spring的代理是通过动态代理机制实现的。在Spring中,主要有两种代理方式:JDK动态代理和CGLIB动态代理。
- JDK动态代理:JDK动态代理是基于接口的代理方式。它要求目标对象实现一个接口,并由代理对象实现该接口,通过反射机制来实现方法的调用。JDK动态代理的核心类是Proxy和InvocationHandler。Proxy是生成代理对象的工具类,InvocationHandler是一个接口,用于在代理对象执行方法时进行增强处理。
- 创建一个实现InvocationHandler接口的代理处理器类,实现invoke()方法,在invoke()方法中可以定义对目标对象方法的增强逻辑。
- 使用Proxy的newProxyInstance()方法获取代理对象,传入目标对象的类加载器、目标对象的接口、代理处理器对象。
- 通过代理对象调用方法,实际上是调用代理处理器的invoke()方法,从而实现对目标对象方法的增强逻辑。
JDK动态代理的优势是实现简单、使用方便,但要求目标对象实现接口。
- CGLIB动态代理:CGLIB动态代理是基于类的代理方式。它不要求目标对象实现接口,通过继承目标对象生成代理对象,并重写目标对象的方法,在方法中实现对目标对象方法的增强。
使用CGLIB动态代理,需引入cglib库,并在Spring配置文件中配置
的proxy-target-class属性为true,启用CGLIB动态代理。 - 引入cglib库,并在Spring配置文件中配置CGLIB代理。
- 创建一个MethodInterceptor接口的实现类,实现其中的intercept()方法,在intercept()方法中可以定义对目标对象方法的增强逻辑。
- 通过Enhancer类的create()方法获取代理对象,传入目标对象的类、方法拦截器对象。
- 通过代理对象调用方法,实际上是调用方法拦截器的intercept()方法,从而实现对目标对象方法的增强逻辑。
CGLIB动态代理的优势是不要求目标对象实现接口,可以对目标对象的所有方法进行代理,更加灵活。但生成代理对象的过程比较复杂。
总而言之,Spring的代理是基于动态代理机制实现的,通过Proxy和InvocationHandler或Enhancer和MethodInterceptor实现对目标对象方法的增强处理。通过选择合适的代理方式,可以实现对目标对象的代理增强,从而实现各种功能,如事务管理、性能监控等。
1年前 -
Spring框架提供了多种代理实现方式,可以根据需求选择合适的方式。
-
JDK动态代理:
JDK动态代理是Spring框架默认的代理实现方式,它基于Java的反射机制,在运行时动态地生成代理类。使用JDK动态代理,可以通过接口创建代理对象,并将代理对象用作原始对象的替代品。使用JDK动态代理时,需要使用InvocationHandler接口来定义方法调用的处理逻辑。 -
CGLIB动态代理:
CGLIB动态代理是另一种常用的代理实现方式,它通过继承原始对象的方式,生成一个新的子类作为代理类。相比于JDK动态代理,CGLIB动态代理可以代理没有实现接口的类。使用CGLIB动态代理时,需要使用MethodInterceptor接口来定义方法调用的处理逻辑。 -
静态代理:
静态代理是最简单的代理实现方式,它需要手动创建代理类,并将原始对象和代理对象一起编译和部署。在静态代理中,代理对象和原始对象需要实现相同的接口,代理对象在调用原始对象的方法之前或之后执行一些额外的逻辑。 -
基于注解的代理实现:
Spring框架提供了基于注解的代理实现方式,通过在类或方法上添加注解,可以自动地生成代理对象,并进行相关的增强操作。常用的注解包括@Aspect、@Pointcut、@Before、@After等。使用基于注解的代理实现,可以在不修改原始类代码的情况下,实现对原始类的增强。 -
异步代理:
Spring框架还提供了异步代理的功能,通过@Async注解可以将方法标记为异步执行。异步代理会在调用异步方法时,将方法的执行拦截,并将其放入线程池中异步执行,从而提高系统的并发能力和响应性能。
总结来说,Spring框架的代理实现方式有JDK动态代理、CGLIB动态代理、静态代理和基于注解的代理实现等。根据不同的需求,可以选择适合的方式来实现代理。
1年前 -
-
Spring的代理是通过AOP(面向切面编程)来实现的。在Spring框架中,可以使用两种方式来实现代理:JDK动态代理和CGLIB动态代理。
JDK动态代理是通过Java的反射机制来实现的,只能对接口进行代理。而CGLIB动态代理是通过继承的方式来实现的,可以对类进行代理。
下面分别介绍JDK动态代理和CGLIB动态代理的实现方式和操作流程。
一、JDK动态代理
JDK动态代理需要有接口来进行代理,所以首先需要定义一个接口。接口的方法就是代理的方法。
- 创建一个接口
public interface UserService { void addUser(String name); }- 实现接口的类
public class UserServiceImpl implements UserService { @Override public void addUser(String name) { System.out.println("添加用户:" + name); } }- 创建一个代理类实现InvocationHandler接口
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class UserServiceProxy implements InvocationHandler { private Object target; public UserServiceProxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("前置通知"); Object result = method.invoke(target, args); System.out.println("后置通知"); return result; } }- 创建代理对象
import java.lang.reflect.Proxy; public class ProxyDemo { public static void main(String[] args) { UserService userService = new UserServiceImpl(); UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new UserServiceProxy(userService)); proxy.addUser("John"); } }运行上述代码,将会在控制台上看到如下输出:
前置通知 添加用户:John 后置通知通过以上步骤,就实现了JDK动态代理。
二、CGLIB动态代理
CGLIB动态代理不需要有接口,可以对类进行代理。使用CGLIB动态代理,需要引入CGLIB相关的jar包。
- 创建一个类
public class UserService { public void addUser(String name) { System.out.println("添加用户:" + name); } }- 创建一个代理类
import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.springframework.cglib.proxy.Enhancer; import java.lang.reflect.Method; public class UserServiceProxy implements MethodInterceptor { private Object target; public UserServiceProxy(Object target) { this.target = target; } public Object getProxyInstance() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("前置通知"); Object result = proxy.invokeSuper(obj, args); System.out.println("后置通知"); return result; } }- 创建代理对象
public class ProxyDemo { public static void main(String[] args) { UserService userService = new UserService(); UserServiceProxy proxy = new UserServiceProxy(userService); UserService userServiceProxy = (UserService) proxy.getProxyInstance(); userServiceProxy.addUser("John"); } }运行上述代码,将会在控制台上看到如下输出:
前置通知 添加用户:John 后置通知通过以上步骤,就实现了CGLIB动态代理。
总结
Spring的代理是通过AOP实现的,可以选择JDK动态代理或者CGLIB动态代理来实现代理功能。JDK动态代理适用于有接口的类,而CGLIB动态代理适用于没有接口的类。无论是JDK动态代理还是CGLIB动态代理,都可以在方法执行前后进行一些额外的操作,例如前置通知和后置通知。代理对象可以通过Spring容器来创建,也可以通过代码手动创建。
1年前