AOP底层实现原理

作者: zhl 分类: Spring 发布时间: 2024-05-09 10:29

一、JDK

  • 核心思想:
    原始类和代理类实现相同的接口

使用JDK自带api创建动态代理

public class JDKTest{
    public static void main(String[] args){
        // 获取原始对象
        UserService userService = new UserServiceImpl();

        ClassLoader classLoader = JDKTest.class.getClassLoader();
        Class<?>[] interfaces = userService.getClass().getInterfaces();
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("====执行原始方法之前====");
                // 运行原始方法
                Object ret = method.invoke(userService, args);
                System.out.println("====执行原始方法之后====");
                return ret;
            }
        };
        UserService userServiceProxy = (UserService)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        userServiceProxy.register(new User());
        userServiceProxy.login("zhl", "123");
    }
}
  1. 类加载器的作用(ClassLoader)
    类加载器把对应类的字节码文件(.class)加载到JVM,创建这个类的Class对象,进而创建这个类的对象。
    动态字节码技术没有创建代理类的源文件和字节码文件,但是需要创建动态代理类的对象,所以需要借用一个类加载器。
  2. interfaces
    原始类实现的接口
  3. InvocationHandler
    为原始类中的原始方法添加额外功能

二、Cglib

  • 核心思想:
    代理类继承原始类

使用Cglib创建动态代理,创建过程大致和JDK方式类似

public class CglibTest {
    public static void main(String[] args) {
        // 原始对象
        UserService userService = new UserService();

        Enhancer enhancer = new Enhancer();
        // 为动态代理类设置类加载器
        enhancer.setClassLoader(CglibTest.class.getClassLoader());
        // 设置原始类为父类,添加额外功能
        enhancer.setSuperclass(userService.getClass());
        MethodInterceptor interceptor = new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("----------cglib before--------");
                Object ret = method.invoke(userService, args);
                System.out.println("----------cglib after--------");
                return ret;
            }
        };
        // callback <===> invocationHandler
        enhancer.setCallback(interceptor);

        // 创建代理对象
        UserService serviceProxy = (UserService) enhancer.create();
        serviceProxy.login("zzz", "222");
        serviceProxy.register(new User());
    }
}

三、BeanPostProcessor

Spring工厂如何加工原始对象?
思路分析:

简单代码实现:

public class ProxyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        InvocationHandler invocation = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("--------核心功能之前---------");
                Object ret = method.invoke(bean, args);
                System.out.println("--------核心功能之后---------");
                return ret;
            }
        };

        return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(),invocation);
    }
}
<bean id="userService" class="com.zhl.factory.UserServiceImpl"/>
<!--对当前配置文件中的所有bean进行加工-->
<bean id="proxyBeanPostProcessor" class="com.zhl.factory.ProxyBeanPostProcessor"/>

这里的实现比较粗糙,没有引入切入点,对整个Spring工厂中的bean都进行了加工。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注