spring的动态代理是如何实现的
-
Spring的动态代理是通过底层的JDK动态代理和CGLIB动态代理来实现的。具体来说,Spring会根据被代理对象的接口或者类,决定使用哪一种方式来生成代理类。
1、JDK动态代理
JDK动态代理是基于接口的代理,它利用Java的反射机制动态地生成一个实现了被代理接口的代理类。JDK动态代理要求被代理的对象必须实现一个或多个接口。当调用被代理接口的方法时,代理类会通过调用InvocationHandler的invoke方法来触发相应的拦截逻辑。在invoke方法中,可以对方法进行增强、记录日志等操作。JDK动态代理的生成过程主要包括以下步骤:
(1) 定义一个实现InvocationHandler接口的代理类,实现invoke方法来实现拦截逻辑;
(2) 使用Proxy类的newProxyInstance方法动态生成代理对象。2、CGLIB动态代理
CGLIB动态代理是基于类的代理,它通过继承被代理类来生成一个子类,并重写其中的方法进行拦截。相比JDK动态代理,CGLIB动态代理不要求被代理对象实现接口,因此可以对任意的类进行代理。当调用被代理类的方法时,代理类会通过调用MethodInterceptor的intercept方法来实现拦截逻辑。在intercept方法中,可以对方法进行增强、记录日志等操作。CGLIB动态代理的生成过程主要包括以下步骤:
(1) 定义一个实现MethodInterceptor接口的代理类,实现intercept方法来实现拦截逻辑;
(2) 使用Enhancer类的create方法动态生成代理对象。在使用Spring的动态代理时,可以通过配置文件或者注解的方式来指定使用哪一种代理方式。通常情况下,如果被代理对象实现了接口,Spring会使用JDK动态代理;如果被代理对象没有实现接口,Spring会使用CGLIB动态代理。但是也可以通过配置来强制使用某一种代理方式。
总结:Spring的动态代理是通过底层的JDK动态代理和CGLIB动态代理来实现的,根据被代理对象的接口或者类的不同,决定使用哪一种方式来生成代理类。JDK动态代理适用于基于接口的代理,CGLIB动态代理适用于基于类的代理。
1年前 -
Spring的动态代理是通过Java的反射机制实现的。动态代理允许在运行时创建代理对象,这些代理对象可以在被调用时拦截方法调用并执行额外的逻辑。
Spring使用了两种类型的动态代理:基于JDK的动态代理和基于CGLIB(Code Generation Library)的动态代理。
-
基于JDK的动态代理:JDK动态代理是通过接口来实现的代理。它要求目标类必须实现接口,并且代理类与目标类实现相同的接口。JDK动态代理利用了Java的反射机制,在运行时创建一个实现了目标接口的代理对象。当调用代理对象的方法时,实际上是调用了代理类中的invoke方法。在invoke方法中,可以通过Method对象获取到被代理方法的信息,然后根据需要执行一些额外的逻辑。
-
基于CGLIB的动态代理:CGLIB是一个开源的代码生成库,可以在运行时生成Java类的字节码并动态加载到JVM中。CGLIB动态代理不需要目标类实现接口,而是通过继承目标类来创建代理对象。CGLIB动态代理通过Enhancer类和MethodInterceptor接口实现。Enhancer类负责生成代理类的字节码,而MethodInterceptor接口负责拦截方法调用并执行额外的逻辑。
-
动态代理的使用场景:动态代理可以用于实现AOP(面向切面编程)。通过使用动态代理,可以将一些通用的行为,如日志记录、事务管理等,从目标类中解耦出来,并在运行时动态地将其插入到目标方法的前后。这样可以提高代码的重用性和可维护性。
-
JDK动态代理与CGLIB动态代理的选择:如果目标类实现了接口,那么通常使用JDK动态代理。因为使用JDK动态代理要求代理类和目标类实现相同的接口,所以只能代理接口定义的方法。而CGLIB动态代理可以代理任意的类和方法,包括final类和final方法。但是CGLIB动态代理使用了字节码生成技术,所以相对于JDK动态代理来说,会稍微耗费更多的资源。
-
使用Spring的AOP支持:Spring框架为动态代理提供了完整的支持。通过配置文件或注解,可以将切面逻辑与目标类进行绑定,从而实现AOP功能。Spring AOP底层使用了动态代理来生成代理对象,并在方法调用前后执行切面逻辑。这样,我们可以将一些通用的行为,如事务管理、异常处理等,从业务逻辑中分离出来,提高代码的可读性和可维护性。
1年前 -
-
Spring框架中的动态代理是通过使用Java的反射机制和Java动态代理机制实现的。Spring框架提供了两种动态代理的方式:JDK动态代理和CGLIB动态代理。
- JDK动态代理:
JDK动态代理是基于接口的代理,它要求被代理对象必须实现一个接口。JDK动态代理使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。
实现步骤如下:
- 创建一个实现
InvocationHandler接口的代理处理类,重写invoke方法,在invoke方法中进行代理逻辑的编写。 - 使用
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法创建代理对象,其中loader参数是类加载器,interfaces参数是被代理对象实现的接口,h参数是代理处理器对象。 - 通过代理对象调用方法时,实际上会调用代理处理器的
invoke方法,根据方法名和参数进行相应的处理。
示例代码如下:
public interface Foo { void bar(); } public class FooProxy implements InvocationHandler { private Object target; public FooProxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在方法调用前进行处理 System.out.println("Before method call"); // 调用被代理对象的方法 Object result = method.invoke(target, args); // 在方法调用后进行处理 System.out.println("After method call"); return result; } public static void main(String[] args) { Foo foo = new FooImpl(); FooProxy proxy = new FooProxy(foo); Foo proxyObj = (Foo) Proxy.newProxyInstance(FooProxy.class.getClassLoader(), new Class[]{Foo.class}, proxy); proxyObj.bar(); } }- CGLIB动态代理:
CGLIB动态代理是基于继承的代理,它不要求被代理对象实现接口。CGLIB动态代理使用net.sf.cglib.proxy.Enhancer类来生成代理类。
实现步骤如下:
- 创建一个实现
MethodInterceptor接口的代理处理类,重写intercept方法,在intercept方法中进行代理逻辑的编写。 - 使用
Enhancer.create(Class superClass, Callback callback)方法创建代理对象,其中superClass参数是被代理对象的类,callback参数是代理处理器对象。 - 通过代理对象调用方法时,实际上会调用代理处理器的
intercept方法,根据方法名和参数进行相应的处理。
示例代码如下:
public class Foo { public void bar() { System.out.println("Foo bar"); } } public class FooProxy implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在方法调用前进行处理 System.out.println("Before method call"); // 调用被代理对象的方法 Object result = proxy.invokeSuper(obj, args); // 在方法调用后进行处理 System.out.println("After method call"); return result; } public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Foo.class); enhancer.setCallback(new FooProxy()); Foo proxyObj = (Foo) enhancer.create(); proxyObj.bar(); } }总结:
Spring框架的动态代理机制通过使用Java的反射和动态代理机制,可以在运行时动态地生成代理类,并在代理过程中进行一些额外的操作。 JDK动态代理适用于接口代理,CGLIB动态代理适用于类代理。开发者可以根据具体的需求选择合适的动态代理方式。1年前 - JDK动态代理: