Spring动态代理广泛应用于Spring AOP等场景,所以要掌握好Spring需要学习深入Spring动态代理@mikechen
什么是动态代理
动态代理是一种在运行时生成代理类的技术,它允许我们在不修改目标对象的情况下,通过代理对象来控制目标对象的行为。
什么是Spring动态代理
在Spring框架中动态代理是一个非常重要的特性,它允许开发者通过代理对象来实现AOP编程,从而实现对目标对象的控制。
Spring动态代理使用场景
Spring框架中广泛使用了动态代理技术,用于实现Spring AOP(面向切面编程)。
AOP是一种编程范式,通过将通用的功能,比如:事务管理、日志记录等与业务逻辑分离,使代码更易于维护和扩展。
Spring动态代理实现方式
Spring中的动态代理主要有两种:JDK动态代理和CGLIB动态代理。
1.JDK动态代理
JDK动态代理是基于接口的代理,它只能为实现了接口的类创建代理对象。
JDK 动态代理是不需要第三方库支持,只需要 JDK 环境就可以进行代理,使用条件:
- 业务目标对象实现接口;
- 实现 InvocationHandler 接口;
- 使用 Proxy.newProxyInstance() 方法生成代理对象;
1.创建InvocationHandler对象
在创建代理对象时,我们需要先创建一个InvocationHandler对象。
InvocationHandler是一个接口,它有一个invoke方法,代理对象的所有方法调用都会被重定向到invoke方法中进行处理。
2.创建代理类
在创建代理对象时,我们需要通过Proxy类的静态方法newProxyInstance来创建代理类。
在创建代理类时,JDK动态代理会自动在内存中生成一个代理类,并在代理类中实现InvocationHandler接口的invoke方法。
3.调用代理类的方法
在代理类中,所有方法调用都会被重定向到InvocationHandler接口的invoke方法中进行处理。
invoke方法中会通过反射调用目标对象的方法,并在方法前后执行一些增强逻辑,从而实现对目标对象的控制。
下面是JDK动态代理的代码实现:
public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method"); Object result = method.invoke(target, args); System.out.println("after method"); return result; } public static void main(String[] args) { RealSubject realSubject = new RealSubject(); DynamicProxy dynamicProxy = new DynamicProxy(realSubject); Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), dynamicProxy); subject.doSomething(); } } interface Subject { void doSomething(); } class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } }
2.CGLIB动态代理
CGLIB动态代理是基于继承的代理,它可以为任何类创建代理对象,包括没有实现接口的类。
CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。
CGLIB动态代理的优点是可以为任何类创建代理对象,缺点是速度比JDK动态代理慢,效率相对较低。
下面是一个使用CGLIB动态代理的例子:
public class UserService { public void addUser(String name) { System.out.println("add user: " + name); } } public class UserServiceProxy implements MethodInterceptor { private Object target; public UserServiceProxy(Object target) { this.target = target; } public Object createProxy() { 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("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 UserService(); UserServiceProxy userServiceProxy = new UserServiceProxy(userService); UserService proxy = (UserService) userServiceProxy.createProxy(); proxy.addUser("Tom"); } }
以上就是Spring动态代理详解,更多Spring内容请查看:Spring教程(史上最全图文详解)
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》