Spring动态代理详解(实现方式及使用场景)

Spring动态代理详解(实现方式及使用场景)-mikechen

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的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。

Spring动态代理详解(实现方式及使用场景)-mikechen

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面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法