spring默认使用什么代理
-
Spring默认使用JDK动态代理。在Spring中,当我们配置AOP时,默认情况下,如果目标对象实现了接口,则使用JDK动态代理;如果目标对象没有实现接口,则使用CGLIB代理。
JDK动态代理是通过Java的反射机制在运行时动态地创建目标对象的代理对象。它要求目标对象必须实现至少一个接口,在运行时生成一个实现了目标对象接口的代理类,代理类会实现接口中的所有方法,并在方法调用前后执行额外的逻辑。
CGLIB代理是通过继承目标对象创建的代理对象。它不要求目标对象实现接口,而是直接继承目标对象的类并重写其中的方法来添加额外逻辑。CGLIB代理是通过字节码技术生成目标对象的子类,并在子类中拦截代理方法的调用。
Spring选择使用JDK动态代理还是CGLIB代理的规则如下:
- 如果目标对象实现了接口,则使用JDK动态代理。
- 如果目标对象没有实现接口,则使用CGLIB代理。
当然,我们也可以通过配置来强制使用某种类型的代理。在Spring的配置文件中,可以通过设置
proxy-target-class属性来强制使用CGLIB代理,或者通过设置expose-proxy属性来使代理对象可以通过AopContext.currentProxy()方法获取到自身的代理。1年前 -
Spring默认使用基于JDK动态代理的代理机制。
-
JDK动态代理:
JDK动态代理是指在运行时动态生成代理类的机制。它是通过反射机制来实现的,利用Java的接口和实现类的关系来生成代理对象。JDK动态代理只能对实现了接口的类进行代理,不能对类进行代理。 -
实现原理:
JDK动态代理利用Java的反射机制,在运行时动态生成代理类。当使用代理类调用方法时,会先通过InvocationHandler接口的invoke()方法,将方法的调用转发到InvocationHandler对象中的invoke()方法中处理,这样就可以在代理对象的方法执行前后做一些自定义操作。 -
使用方式:
使用JDK动态代理,需要实现InvocationHandler接口,并重写invoke()方法,来实现方法的调用拦截和处理。然后通过Proxy类的newProxyInstance()方法,传入类加载器、接口,和InvocationHandler对象,来生成代理对象。 -
优缺点:
JDK动态代理的优点是使用方便,不需要额外依赖,且支持多个接口的代理。缺点是只能对实现接口的类进行代理,对于没有接口的类则无法进行代理。 -
使用场景:
JDK动态代理适用于有明确接口的情况下,例如服务层进行日志、事务等公共操作的处理。同时,由于JDK动态代理是Java原生支持的,因此在性能上相对较高,适用于对性能要求较高的场景。
总结:Spring默认使用基于JDK动态代理的代理机制,通过反射机制,在运行时动态生成代理类并实现方法的调用拦截和处理。JDK动态代理适用于对性能要求较高,且有明确接口的情况下。
1年前 -
-
Spring框架中默认使用的是基于JDK的动态代理(JDK dynamic proxy)。在使用Spring AOP(Aspect Oriented Programming,面向切面编程)进行方法拦截时,Spring会自动选择合适的代理方式,其中JDK动态代理是首选。
JDK动态代理是Java提供的一种在运行时生成代理类的机制。它通过对接口的实现来创建代理对象。当一个类实现了一个接口,并且使用Proxy类的newProxyInstance()方法创建代理对象时,JDK动态代理会动态生成一个代理类,在调用代理对象的方法时,会透明地调用代理类中对应的方法。
下面是Spring默认使用JDK动态代理的方法和操作流程:
- 定义接口和实现类
首先,定义一个接口,然后编写接口的实现类。例如,定义一个名为UserService的接口和一个名为UserServiceImpl的实现类。
public interface UserService { void addUser(User user); User getUser(int userId); } public class UserServiceImpl implements UserService { public void addUser(User user) { // 添加用户的实现逻辑 } public User getUser(int userId) { // 获取用户的实现逻辑 return null; } }- 创建切面类
接下来,创建一个切面类,用于定义切点和增强逻辑。切点指定了哪些方法需要被拦截,而增强逻辑则定义了在方法被拦截时所要执行的代码。例如,创建一个名为LoggingAspect的切面类。
@Aspect public class LoggingAspect { @Before("execution(* com.example.UserService.addUser(..))") public void beforeAddUser(JoinPoint joinPoint) { System.out.println("Before addUser method"); } @AfterReturning(pointcut = "execution(* com.example.UserService.getUser(..))", returning = "result") public void afterReturningGetUser(JoinPoint joinPoint, Object result) { System.out.println("AfterReturning getUser method"); } }- 配置Spring AOP
在Spring的配置文件中,通过配置aop命名空间和相应的标签,来开启和配置AOP。例如,通过在Spring配置文件中添加以下内容来开启AOP,并指定切面类。
<aop:aspectj-autoproxy/> <bean id="loggingAspect" class="com.example.LoggingAspect"/>- 使用代理对象
在代码中使用代理对象时,需要通过Spring的IoC(Inversion of Control,控制反转)容器来获取代理对象。例如,在一个Spring MVC的控制器类中使用UserService的代理对象。
@Controller public class UserController { @Autowired private UserService userService; // 调用代理对象的方法 public void addUser(User user) { userService.addUser(user); } }通过以上步骤,Spring会自动在运行时创建一个代理对象,并在方法调用时应用切面逻辑。默认情况下,Spring会选择使用JDK动态代理来实现代理对象。
1年前 - 定义接口和实现类