动态代理增强 Spring bean

代理模式

生成一个扩展的类代替原来的类,可以不改变原始类代码的前提下增强原始类的功能

分为静态代理和动态代理,动态代理又有两种实现方式分别是:JDK和cglib

静态代理:一个代理类只能代理一个原始类,所以每个代理类都要手动编写代理类(硬编码)

动态代理:在 JVM 运行时动态根据原始类创建代理类,避免硬编码

静态代理

// 定义接口
interface Subject {
    void request();
}
 
// 目标类
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}
 
// 代理类
class ProxySubject implements Subject {
    private RealSubject realSubject;
 
    public ProxySubject() {
        this.realSubject = new RealSubject();
    }
 
    @Override
    public void request() {
        // 增强功能:在请求前后添加日志
        System.out.println("ProxySubject: Logging before request.");
        realSubject.request();
        System.out.println("ProxySubject: Logging after request.");
    }
}

JDK 动态代理增强 Spring bean

@Component
public class Test implements BeanPostProcessor, ApplicationContextAware {
 
    private ApplicationContext applicationContext;
 
    // ApplicationContextAware 回传 IOC 容器
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
 
  	// bean 后置处理器的后置处理
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof User) { // 只增强 User bean
            User user = (User) applicationContext.getBean("user");
            return Proxy.newProxyInstance(
                    user.getClass().getClassLoader(),
                    user.getClass().getInterfaces(), // 原始的 bean 必须要实现接口!(原始类没有实现接口时就要使用 cglib )
                    (Object proxy, Method method, Object[] args) -> {
                        if (method.getName().equals("sayHello")){ // 只增强 sayHello 方法
                            System.out.println("执行前.....");
                            Object invoke = method.invoke(user, args); // 执行目标方法(捕获异常实现环绕通知)
                            System.out.println("执行后.....");
                            return invoke;
                        }
                      	return method.invoke(user, args);
                    }
            );
        }
        return bean; // 如果 bean 不是 User 直接返回原来的
    }
}

cglib 动态代理增强 Spring bean

@Component
public class Test implements BeanPostProcessor, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof User) { // 只增强 User bean
            User user = (User) applicationContext.getBean("user");
            
            // 创建 CGLIB 增强器
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(user.getClass()); // 生成的代理代理类继承自是原始类(原始类不需要实现接口)
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    if (method.getName().equals("sayHello")) { // 只增强 sayHello 方法
                        System.out.println("执行前.....");
                        Object result = proxy.invokeSuper(obj, args); // 调用父类方法
                        System.out.println("执行后.....");
                        return result;
                    }
                    return proxy.invokeSuper(obj, args); // 其他方法直接调用
                }
            });
            
            return enhancer.create(); // 创建代理实例
        }
        return bean; // 如果 bean 不是 User 直接返回原来的
    }
}
posted @ 2024-11-02 20:38  CyrusHuang  阅读(28)  评论(0)    收藏  举报