欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring IOC AOP的手写实现(二)

程序员文章站 2022-07-12 13:10:17
...

IOC的实现

1.1 BeanFactory的生命流程

  1. BeanFactory加载Bean配置文件,将读到的Bean配置封装成BeanDefinition对象
  2. 将封装好的BeanDefinition对象注册到BeanDefinition容器
  3. 注册BeanPostProcessor相关实现类到BeanPostProcessor容器
  4. BeanFactory进入就绪状态
  5. 外部调用BeanFactory的getBean(String name)方法,BeanFactory着手实例化相应的bean
  6. 重复3、4,直至程序退出,BeanFactory被销毁

1.2 BeanDefinition及其他一些类的介绍

  • BeanDefinition:作用是根据Bean的配置信息生产成本相应的Bean详情对象,如果把Bean比喻为电脑 ,那么BeanDefinition就是电脑的配置清单,可以透过电脑看到电脑的详细配置。

  • BeanReference:保存bean配置中ref属性对应的值,在后续BeanFactory实例化bean时,会根据BeanReference保存的值去实例化bean所依赖的其他bean。

  • PropertyValuesPropertyValue

    • PropertyValue:name、value字段记录bean标签中的属性值

    • PropertyValues:虽然只是上面的复数形式,也就是相当于一个属性的List集合,那为什么不直接使用List而要定义一个新的类呢?——为了获得一定的控制权

      比如:定义这个PropertyValues类把对属性的列表加入操作封装起来,内部可以添加一些其他的处理,之后再调用List的add方法

1.3 xml的解析

BeanFactory初始化时,会根据传入的xml配置文件路径来加载配置文件,然而BeanFactory值需要管理容器中的bean就可以了,加载和解析配置文件的任务由BeanDefinitionReader的实现类XmlBeanDefinitionReader去做就可以了

  1. 将xml配置文件加载到内存中
  2. 获取根标签下的所有标签
  3. 遍历获取到的标签列表,取出id、class属性
  4. 创建BeanDefinition对象,并将刚刚读取到的id、class属性保存到对象中
  5. 遍历标签下的标签,读取属性值并保存到对象中
  6. 将<id,BeanDefinition>键值对缓存在Map中,留在后面使用
  7. 重复3、4、5、6步,直至解析结束

1.4注册BeanPostProcessor

BeanPostProcessor是Spring对外拓展的接口之一,主要用途:提供一个机会,让开发人员能够插手bean的实例化过程。我们可以在bean实例化的过程中对bean进行一些处理,比如AOP织入相关bean中。

康康BeanFactory如何注册BeanPostProcessor相关实现类的

XmlBeanDefinitionReader在完成解析工作后,BeanFactory会将键值对<id,BeanDefinition>注册到自己的beanDefinitionMap中。BeanFactory注册好BeanDefinition后,就立即开始注册BeanPostProcessor的相关实现类。这个过程

  1. 根据BeanDefinition记录的信息,寻找所有实现了BeanPostProcessor的接口的类
  2. 实例化BeanPostProcessor接口的实现类
  3. 将实例化好的对象放入List
  4. 重复2、3步,直至所有的实现类完成注册

1.5 getBean过程解析

在完成xml的解析,BeanDefinition的注册,以及BeanPostProcessor的注册后,BeanFactory的初始化工作就算是结束了,此时BeanFactory处于就绪状态,等待外部程序的调用。它具有延迟实例化bean的特性,也就是等外部程序需要的时候,才实例化。这样做

  • 提高BeanFactory的初始化速度
  • 节省内存资源

看看Spring bean实例化过程 :

Spring IOC AOP的手写实现(二)

我们仿写的过程中简化流程:

  1. 实例化bean对象
  2. 设置对象属性: 将配置文件中配置的属性填充到刚刚创建的 bean 对象中
  3. 检查Aware相关接口并设置相关依赖
  4. BeanPostProcessor前置处理 postProcessBeforeInitialization(Object bean, String beanName)
  5. BeanPostProcessor后置处理 postProcessAfterInitialization(Object bean, String beanName)
  6. 使用中

先看相关的接口:

BeanFactory接口:

/**
 * 工厂接口
 */
public interface BeanFactory {
    Object getBean(String beanId) throws Exception;
}

BeanFactoryAware接口:设置为别的BeanFactory

public interface BeanFactoryAware {

    void setBeanFactory(BeanFactory beanFactory) throws Exception;
}

BeanDefinitionReader接口:把配置文件读到BeanDefinition中去

public interface BeanDefinitionReader {

    void loadBeanDefinitions(String location) throws FileNotFoundException, Exception;

}

BeanPostProcessor 插手实例化的接口:

public interface BeanPostProcessor {

    /**
     * 前置处理
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception;

    /**
     * 后置处理
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws Exception;
}

BeanDefinition类:提供了相应属性值和get、set方法

public class BeanDefinition {

    private Object bean;

    private Class beanClass;

    private String beanClassName;

    private PropertyValues propertyValues = new PropertyValues();

    public BeanDefinition() {
    }

    public void setBean(Object bean) {
        this.bean = bean;
    }

    public Class getBeanClass() {
        return beanClass;
    }

    public void setBeanClass(Class beanClass) {
        this.beanClass = beanClass;
    }

    public String getBeanClassName() {
        return beanClassName;
    }

    public void setBeanClassName(String beanClassName) {
        this.beanClassName = beanClassName;
        try {
            this.beanClass = Class.forName(beanClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public Object getBean() {
        return bean;
    }

    public PropertyValues getPropertyValues() {
        return propertyValues;
    }

    public void setPropertyValues(PropertyValues propertyValues) {
        this.propertyValues = propertyValues;
    }
}

BeanReference类:bean的引用

public class BeanReference {

    private String name;

    private Object bean;

    public BeanReference(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object getBean() {
        return bean;
    }

    public void setBean(Object bean) {
        this.bean = bean;
    }
}

PropertyValue、PropertyValues:属性值

public class PropertyValue {

    private final String name;

    private final Object value;

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }
}
public class PropertyValues {

    private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();

    public void addPropertyValue(PropertyValue pv) {
        // 在这里可以对参数值 pv 做一些处理,如果直接使用 List,则就不行了
        this.propertyValueList.add(pv);
    }

    public List<PropertyValue> getPropertyValues() {
        return this.propertyValueList;
    }

}

XmlBeanDefinitionReader: 解析 xml

public class XmlBeanDefinitionReader implements BeanDefinitionReader {

    private Map<String,BeanDefinition> registry;

    public XmlBeanDefinitionReader() {
        registry = new HashMap<>();//实例化的时候才加载map
    }

    /**
     * 读入配置文件,加载BeanDefinitions
     */
    @Override
    public void loadBeanDefinitions(String location) throws Exception {
        InputStream inputStream = new FileInputStream(location);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = factory.newDocumentBuilder();
        Document doc = docBuilder.parse(inputStream);
        Element root = doc.getDocumentElement();
        parseBeanDefinitions(root);
    }

    /**
     * 遍历root结点
     */
    private void parseBeanDefinitions(Element root) throws Exception {
        NodeList nodes = root.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                parseBeanDefinition(ele);
            }
        }
    }

    /**
     * 遍历bean
     */
    private void parseBeanDefinition(Element ele) throws Exception {
        String name = ele.getAttribute("id");
        String className = ele.getAttribute("class");
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanClassName(className);
        processProperty(ele, beanDefinition);
        registry.put(name, beanDefinition);
    }

    /**
     * 遍历属性
     */
    private void processProperty(Element ele, BeanDefinition beanDefinition) {
        NodeList propertyNodes = ele.getElementsByTagName("property");
        for (int i = 0; i < propertyNodes.getLength(); i++) {
            Node propertyNode = propertyNodes.item(i);
            if (propertyNode instanceof Element) {
                Element propertyElement = (Element) propertyNode;
                String name = propertyElement.getAttribute("name");
                String value = propertyElement.getAttribute("value");
                if (value != null && value.length() > 0) {
                    beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));
                } else {
                    String ref = propertyElement.getAttribute("ref");
                    if (ref == null || ref.length() == 0) {
                        throw new IllegalArgumentException("ref config error");
                    }
                    BeanReference beanReference = new BeanReference(ref);
                    beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanReference));
                }
            }
        }
    }

    /**
     * 获取Map
     */
    public Map<String, BeanDefinition> getRegistry() {
        return registry;
    }
}

XmlBeanFactory:

public class XmlBeanFactory implements BeanFactory {

    /**
     * 把<id,BeanDefinition>的键值对注册到这个里头
     */
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    private List<String> beanDefinitionNames = new ArrayList<>();

    private List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();

    /**
     * 关联过来
     */
    private XmlBeanDefinitionReader beanDefinitionReader;


    public XmlBeanFactory(String location) throws Exception {
        beanDefinitionReader = new XmlBeanDefinitionReader();
        loadBeanDefinitions(location);
    }
    /**
     * 获取bean
     */
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition = beanDefinitionMap.get(name);
        if (beanDefinition == null) {
            throw new IllegalArgumentException("no this bean with name " + name);
        }

        Object bean = beanDefinition.getBean();
        if (bean == null) {
            bean = createBean(beanDefinition);
            bean = initializeBean(bean, name);
            beanDefinition.setBean(bean);
        }

        return bean;
    }
    /**
     * 创建Bean,通过反射
     */
    private Object createBean(BeanDefinition bd) throws Exception {
        Object bean = bd.getBeanClass().newInstance();
        applyPropertyValues(bean, bd);

        return bean;
    }
    /**
     * 注入属性
     */
    private void applyPropertyValues(Object bean, BeanDefinition bd) throws Exception {
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(this);
        }
        for (PropertyValue propertyValue : bd.getPropertyValues().getPropertyValues()) {
            Object value = propertyValue.getValue();
            if (value instanceof BeanReference) {
                BeanReference beanReference = (BeanReference) value;
                value = getBean(beanReference.getName());
            }

            try {
                Method declaredMethod = bean.getClass().getDeclaredMethod(
                        "set" + propertyValue.getName().substring(0, 1).toUpperCase()
                                + propertyValue.getName().substring(1), value.getClass());
                declaredMethod.setAccessible(true);

                declaredMethod.invoke(bean, value);
            } catch (NoSuchMethodException e) {
                Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
                declaredField.setAccessible(true);
                declaredField.set(bean, value);
            }
        }
    }
    /**
     * 初始化
     */
    private Object initializeBean(Object bean, String name) throws Exception {
        for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
            bean = beanPostProcessor.postProcessBeforeInitialization(bean, name);
        }

        for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
            bean = beanPostProcessor.postProcessAfterInitialization(bean, name);
        }

        return bean;
    }

    /**
     * 载入BeanDefinition和BeanPostProcessor
     */
    private void loadBeanDefinitions(String location) throws Exception {
        beanDefinitionReader.loadBeanDefinitions(location);
        registerBeanDefinition();
        registerBeanPostProcessor();
    }

    /**
     * 加入到Map中
     */
    private void registerBeanDefinition() {
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionReader.getRegistry().entrySet()) {
            String name = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            beanDefinitionMap.put(name, beanDefinition);
            beanDefinitionNames.add(name);
        }
    }

    /**
     * 
     */
    public void registerBeanPostProcessor() throws Exception {
        List beans = getBeansForType(BeanPostProcessor.class);
        for (Object bean : beans) {
            addBeanPostProcessor((BeanPostProcessor) bean);
        }
    }

    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        beanPostProcessors.add(beanPostProcessor);
    }

    /**
     * 根据类型获取Bean
     */
    public List getBeansForType(Class type) throws Exception {
        List beans = new ArrayList<>();
        for (String beanDefinitionName : beanDefinitionNames) {
            if (type.isAssignableFrom(beanDefinitionMap.get(beanDefinitionName).getBeanClass())) {
                beans.add(getBean(beanDefinitionName));
            }
        }
        return beans;
    }
}

AOP实现

AOP 是基于动态代理模式实现的,具体实现上可以基于 JDK 动态代理或者 Cglib 动态代理。其中 JDK 动态代理只能代理实现了接口的对象,而 Cglib 动态代理则无此限制。

简化实现流程:

  1. AOP 逻辑介入 BeanFactory 实例化 bean 的过程
  2. 根据 Pointcut 定义的匹配规则,判断当前正在实例化的 bean 是否符合规则
  3. 如果符合,代理生成器将切面逻辑 Advice 织入 bean 相关方法中,并为目标 bean 生成代理对象
  4. 将生成的 bean 的代理对象返回给 BeanFactory 容器,到此,AOP 逻辑执行结束

2.2 基于 JDK 动态代理的 AOP 实现

代理对象生成器的逻辑主要写在了 JdkDynamicAopProxy 类中,这个类的有两个方法,其中 getProxy 方法用于生成代理对象。invoke 方法是 InvocationHandler 接口的具体实现,包含了将通知(Advice)织入相关方法中

public abstract class AbstractAopProxy implements AopProxy {

    protected AdvisedSupport advised;

    public AbstractAopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }
}

/**
 * 基于 JDK 动态代理的代理对象生成器
 * Created by code4wt on 17/8/16.
 */
final public class JdkDynamicAopProxy extends AbstractAopProxy implements InvocationHandler {

    public JdkDynamicAopProxy(AdvisedSupport advised) {
        super(advised);
    }

    /**
     * 为目标 bean 生成代理对象
     * @return bean 的代理对象
     */
    @Override
    public Object getProxy() {
        return Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getInterfaces(), this);
    }

    /**
     * InvocationHandler 接口中的 invoke 方法具体实现,封装了具体的代理逻辑
     * @param proxy
     * @param method
     * @param args
     * @return 代理方法或原方法的返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodMatcher methodMatcher = advised.getMethodMatcher();
        
        // 1. 使用方法匹配器 methodMatcher 测试 bean 中原始方法 method 是否符合匹配规则
        if (methodMatcher != null && methodMatcher.matchers(method, advised.getTargetSource().getTargetClass())) {
            
            // 获取 Advice。MethodInterceptor 的父接口继承了 Advice
            MethodInterceptor methodInterceptor = advised.getMethodInterceptor();
            
           /* 
            * 2. 将 bean 的原始方法 method 封装在 MethodInvocation 接口实现类对象中,
            * 并把生成的对象作为参数传给 Adivce 实现类对象,执行通知逻辑
            */ 
            return methodInterceptor.invoke(
                    new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method, args));
        } else {
            // 2. 当前 method 不符合匹配规则,直接调用 bean 的原始方法 method
            return method.invoke(advised.getTargetSource().getTarget(), args);
        }
    }
}

Spring IOC AOP的手写实现(二)

ProxyFactory 实现代码:

/**
 * AopProxy 实现类的工厂类
 */
public class ProxyFactory extends AdvisedSupport implements AopProxy {
    @Override
    public Object getProxy() {
        return createAopProxy().getProxy();
    }

    private AopProxy createAopProxy() {
        return new JdkDynamicAopProxy(this);
    }
}

测试类:

public class XmlBeanFactoryTest {
    @Test
    public void getBean() throws Exception {
        System.out.println("--------- AOP test ----------");
        String location = getClass().getClassLoader().getResource("spring.xml").getFile();
        XmlBeanFactory bf = new XmlBeanFactory(location);
        HelloService helloService = (HelloService) bf.getBean("helloService");
        helloService.sayHelloWorld();
    }
}

测试结果:
Spring IOC AOP的手写实现(二)

相关标签: AOP IOC