Spring手撸源码系列-实现应用上下文及前置后置修改Bean操作

这一篇内容量比较多也不好理解,最好的理解方式是手敲理解,去思考为什么这么设计,好处是什么,学习到了可不可以应用到自己实践项目当中,相信你可以受益匪浅。

咱们要实现两大功能1是实现应用上下文,这个的意思就是说我们在实例化时将配置文件交给上下文类,上下文类会通过内部处理后会解析XML然后将Bean注册并创建出Bean的过程,我们对于使用的话什么都不操作,看看如下的使用入口,是不是更简便了

再看看之前的写法,还需要自己实例化,还得找对应的Bean的解析类等等,咱们优化过后,将所有的数据刷新到容器里就都在上下文操作类做了

 第二个就是可以在Bean解析完后放入Bean定义中时在Bean创建之前修改Bean的信息,然后在实例化后对实例Bean进行修改的操作扩展

BeanFactoryPostProcssor:Bean的前置处理,Bean对象注册后实例化之前对Bean定义信息进行修改操作。

BeanPostProcessor:Bean的后置处理,bean对象实例化之后可以进行Bean的修改,甚至可以更改Bean的对象。

这一期会稍微复杂一点,涉及的改动也会多一点,本期更改完后,后面的扩展都是很方便了,也很简单。

本篇代码github地址:https://github.com/dufGIT/spring-sourcecode.git

1.UML类图

1.1 应用上下文类

1. ApplicationContext:定义上下文接口,表明是上下文接口,继承ListableBeanFactory,ListableBeanFactory是BeanFactory里的,继承此接口Context上下文就有了根据BeanFactoryPostProcssor类以及BeanPostProcssor类来获取对应自定义类,方法为:getBeansOfType(Class<T> type),还有了从BeanDefinition里获取beanName名称集合的功能,方法为:getBeanDefinitionNames(),现在看肯定绕甚至不懂,自己动手敲看代码逻辑,其实就明白我这个段说的意思了。

2. ConfigurableApplicationContext:接口,继承ApplicationContext,定义了刷新方法refresh(),代表要将xml里的bean通过解析刷新到程序容器里的一系列操作。

3. AbstractApplicationContext:抽象类,此类实现ConfigurableApplicationContext类,实现刷新方法refresh(),并继承了DefaultResourceLoader,可获得不同的资源处理器就有了可以处理xml解析数据的入口,此类里还定义了将Bean对象刷新到容器里的方法功能refreshBeanFactory()供子类去实现具体功能,以及定义了获取新添加的ConfigurableListableBeanFactory接口的方法为:getBeanFactory()供子类使用

4. AbstractRefreshableApplicationContext:抽象类,继承AbstractApplicationContext,实现getBeanFactory()以及refreshBeanFactory()方法,定义了loadBeanDefinitions(DefaultListableBeanFactory beanFactory)方法;

5. AbstractXmlApplicationContext:抽象类,继承AbstractRefreshableApplicationContext类,实现loadBeanDefinitions()方法,此方法实现了从xml中解析Bean以后放入到BeanDefinition里。定义了getConfigLocations()方法,用来获取配置文件路径的方法

6.ClassPathXmlApplicationContext:普通类,继承AbstractXmlApplicationContext类,实现getConfigLocations()将获取配置文件路径,此类也是入口,通过构造方法将String路径传入以后调用refresh()刷新方法。

这样一来应用上下文相关的类就都说完了

咱们在回到今天说的主题上上下文说完了,就该说一下Bean的前置和后置修改的情况,前置是在Bean放入了BeanDefinition中时的修改,后置是在创建Bean对象的修改,所以我们大致就知道他们功能的所在位置,一个是refresh()时,将xml里数据解析到BeanDefinition后就可以了,另一个是createBean()方法里已经创建好对象后进行修改操作,那么咱们接下来说一下bean前置后置相关类

1.2 Bean前置后置

1.2.1 BeanFactoryPostProcessor:Bean前置接口,定义了postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)前置方法,所有的为被实例化在Bean容器被定义时即可修改

1.2.2 BeanPostProcessor:Bean后置接口,定义了postProcessBeforeInitialization(),

postProcessAfterInitialization()方法。是在Bean对象创建完毕即可修改

到这一节之前的改动的有点多,原作者为了贴合Spring源码,添加了很多以BeanFactory为结尾的类,还有就是在创建bean后处理自定义修改Bean对象,所以以前的类也需要改动,或方法或继承

1.3 BeanFactory为后缀类的改动

1.3.1 HierarchicalBeanFactory:添加一个BeanFactory接口,暂时没有实际使用,也没有定义方法

1.3.2 ConfigurableBeanFactory:添加一个BeanFactory接口,定义addBeanPostProcessor(BeanPostProcessor beanPostProcessor)方法,代表往容器中添加后置接口,留着子类实现。

1.3.3 ListableBeanFactory:添加一个BeanFactory接口,定义方法getBeansOfType(Class<T> type)方法,这里的作用根据前置后置接口来寻找实现后置与前置的自定义来,目的是这样就可以调用实现方法。getBeanDefinitionNames()暂时需求里没有调用此方法,但是实现了,不算核心。

1.3.3 AutowireCapableBeanFactory:添加一个BeanFactory接口,定义方法applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName),实例化之后的对对象修改。定义修改后返回对象方法applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName);等着子类实现。

1.3.4 ConfigurableListableBeanFactory:添加一个BeanFactory接口,继承了ConfigurableBeanFactory、ListableBeanFactory、AutowireCapableBeanFactory,并定义了getBeanDefinition(String beanName)、preInstantiateSingletons()(此方法是刷新上下文里会调用此方法,在全部处理完后,如果有没有被实例化的进行实例化操作)、addBeanPostProcessor(BeanPostProcessor beanPostProcessor)定义添加后置接口方法

1.3.5 DefaultListableBeanFactory:这个接口修改为实现ConfigurableListableBeanFactory接口,实现preInstantiateSingletons()以及getBeansOfType(Class<T> type)方法。

1.3.6 AbstractAutowireCapableBeanFactory:DefaultListableBeanFactory的继承类,修改为实现AutowireCapableBeanFactory接口,AbstractAutowireCapableBeanFactory类在CreateBean方法里添加initialization(),此方法里又实现了AutowireCapableBeanFactory接口applyBeanPostProcessorsBeforeInitialization()和applyBeanPostProcessorsAfterInitialization()。

以上就是这一期的所有的改动。

2.代码实现

2.1 上下文接口实现

context包下,是此次新增的目录

ApplicationContext:定义上下文接口

public interface ApplicationContext extends ListableBeanFactory{

}

ConfigurableApplicationContext: 继承ApplicationContext,定义刷新方法,是核心方法,需要在其子类实现刷新方法进行将文件里的数据刷新到容器的操作。

public interface ConfigurableApplicationContext extends ApplicationContext {

    /**
     * 刷新容器
     *
     * @throws BeansException
     */
    void refresh() throws BeansException;
}

AbstractApplicationContext:此抽象类继承了DefaultResourceLoader(就有了处理xml中数据的能力),实现接口ConfigurableApplicationContext,就需要具体实现刷新接口,

第一点定义抽象方法refreshBeanFactory()供其他子类实现具体刷新到Bean容器功能,

第二点定义获取BeanFactory方法getBeanFactory(),供其子类实现,

第三点就是通过如果在bean实例化之前有要修改Bean的操作则将自定义操作类调用方法使用,

第四点是如果有BeanPostProcessor则添加到容器里,供后续实例化使用。

第五点是将beanDefinition容器里的数据循环进行获取bean操作,看是否有没被实例化的Bean,有则进行实例化操作

context.supprot包下

// 定义一些基本的上下文
// 定义一些方法,由一层一层子类实现
// 也在本类自实现了如invokeBeanFactoryPostProcessors(),registerBeanPostProcessors()
// 也实现了父类的继承的各个方法
// 实现了ConfigurableApplicationContext接口,实现refresh()
// 第7节加
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    // 使用模板方法
    @Override
    public void refresh() {
        // 1.创建beanFactory
        // 2.将创建完的beanFactory和配置文件路径传输到资源处理器里
        // 3.从资源处理器获取输入流,根据流解析bean以及属性数据并注册到bean容器里
        refreshBeanFactory();

        // 2.获取beanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();


        // 3.在bean实例化之前,执行BeanFactoryPostProcessor(Invoke factory processors registered as beans in the context)
        // 3.1 根据BeanFactoryPostProcessor来判断是否是自定义实现子类,是就创建bean,并注册到单例类(创建自定义类Bean(MyBeanFactoryPostProcessor))
        // 3.2 根据得到的BeanFactoryPostProcessor接口来调用postProcessBeanFactory方法(此时beanDefinition里的属性已经修改)
        invokeBeanFactoryPostProcessors(beanFactory);

        // 4.BeanPostProcessor需要提前于其他Bean对象实例化之前执行注册操作
        // 4.1 通过getBeansOfType()找到与BeanPostProcessor相关的类,
        // 4.2 找到以后调用将当前的BeanPostProcessor放入集合里(做标识-后续其他bean实例创建可进行后置处理更改对象bean)
        registerBeanPostProcessors(beanFactory);

        
        // 5.提前实例化单例bean对象
        // 通过beanDefinationMap里的实例对象将后续bean实例进行实例化,并处理后置修改的对象
        beanFactory.preInstantiateSingletons();


    }

    protected abstract void refreshBeanFactory();

    protected abstract ConfigurableListableBeanFactory getBeanFactory();

    // 在bean实例化之前,执行BeanFactoryPostProcessor,自定义实现进行bean的修改
    private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 获取和BeanFactoryPostProcessor类有关系的的类-这里主要是获取BeanFactoryPostProcessor的子实现接口
        Map<String, BeanFactoryPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanPostProcessorMap.values()) {
            // 调用用户自定义实现的子接口
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        }
    }

    private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 根据BeanPostProcessor获取其子实现接口
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
            // 将beanPostProcessor添加到集合里
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        }
    }


    @Override
    public <T> Map<String, T> getBeansOfType(Class<T> type) {
        return getBeanFactory().getBeansOfType(type);
    }

    @Override
    public String[] getBeanDefinitionNames() {
        return getBeanFactory().getBeanDefinitionNames();
    }

    @Override
    public Object getBean(String name) throws BeansException {
        return getBeanFactory().getBean(name);
    }

    @Override
    public Object getBean(String name, Object... args) {
        return getBeanFactory().getBean(name, args);
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return getBeanFactory().getBean(name, requiredType);
    }
}

AbstractRefreshableApplicationContext:继承AbstractApplicationContext,实现refreshBeanFactory()方法,并定义抽象加载beanDefinition方法loadBeanDefinitions()供其子类实现,实现了父类的方法为getBeanFactory()

// AbstractRefreshableApplicationContext此类主要是1.创建beanFactory,2.定义loadBeanDefinitions,3.定义获取beanFactory
// 此类继承了AbstractApplicationContext,定义了一些方法由当前类实现如:1.refreshBeanFactory(),2 getBeanFactory()
// 刷新应用上下文
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

    private DefaultListableBeanFactory beanFactory;

    @Override
    protected void refreshBeanFactory() {
        // 创建DefaultListableBeanFactory,也就是创建beanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 获取资源并得到数据
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }

    // 创建DefaultListableBeanFactory()类
    private DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory();
    }

    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);

    // 将当前创建的bean直接返回就可
    @Override
    protected ConfigurableListableBeanFactory getBeanFactory() {
        return beanFactory;
    }
}

AbstractXmlApplicationContext:继承AbstractRefreshableApplicationContext类,实现loadBeanDefinitions()方法,解析xml中的bean并放入容器里一系列操作,定义了getConfigLocations()抽象方法,供其子类实现


// AbstractXmlApplicationContext抽象类主要是调用解析xml中的bean并加载到系统里,
// 继承AbstractRefreshableApplicationContext类用来创建beanFactory然后定义loadBeanDefinitions让当前子类实现
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
        // 开始调用上一章节的应用上下文资源解析核心类
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);
        // 改为获取传过来参数配置文件的路径
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            // 获取资源并解析资源里的数据
            beanDefinitionReader.loadBeanDefinitions(configLocations);
        }
    }

    protected abstract String[] getConfigLocations();
}

ClassPathXmlApplicationContext:继承AbstractXmlApplicationContext类,根据外部使用new ClassPathXmlApplicationContext(String path)将配置文件路径传入到此类全局变量里,并调用刷新方法,来完成bean的加载解析注册到容器的操作。


public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
    // 获取配置文件的路径集合:如classpath:useContext.xml
    private String[] configLoctions;

    public ClassPathXmlApplicationContext() {
    }

    /*
     * @Author df
     * @Description 从xml中加载BeanDefinition并刷新上下文。
     * @Date 10:26 2021/11/30
     * @Param [configLocations]
     * @return
     **/
    public ClassPathXmlApplicationContext(String configLocations) {
        this(new String[]{configLocations});
    }

    /*
     * @Author df
     * @Description 从xml中加载BeanDefinition并刷新上下文。
     * @Date 10:26 2021/11/30
     * @Param [configLocations]
     * @return
     **/
    public ClassPathXmlApplicationContext(String[] configLocations) {
        this.configLoctions = configLocations;
        refresh();
    }

    @Override
    protected String[] getConfigLocations() {
        return configLoctions;
    }
}

2.2 bean前置和后置接口

 beans.factory.config包

这个接口是满足于在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制。

public interface BeanFactoryPostProcessor {
    /*
     * @Author df
     * @Description 在所有的BeanDefinition加载完成后,实例化Bean对象之前,提供修改BeanDefinition属性的机制。
     * 相当于在bean对象注册后没有被实例化之前进行bean的修改
     * @Date 11:25 2021/11/24
     * @Param []
     * @return void
     **/
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}

 BeanPostProcessor:接口提供了两个方法:postProcessBeforeInitialization 用于在 Bean 对象执行初始化方法之前,执行此方法、postProcessAfterInitialization用于在 Bean 对象执行初始化方法之后,执行此方法

// 此类可以在bean对象实例化后修改bean对象,当然也可替换对象
public interface BeanPostProcessor {
    /*
     * @Author df
     * @Description 在bean对象执行初始化方法之前,执行此方法
     * @Date 11:29 2021/11/24
     * @Param [bean, beanName]
     * @return java.lang.Object
     **/
    Object postProcessBeforeInitialization(Object bean, String beanName);


    /*
     * @Author df
     * @Description 在bean对象执行初始化方法之后,执行此方法
     * @Date 11:29 2021/11/24
     * @Param [bean, beanName]
     * @return java.lang.Object
     **/
    Object postProcessAfterInitialization(Object bean, String beanName);
}

2.3 BeanFactory类

beans.factory包下

HierarchicalBeanFactory:此类按spring中接口来写的,暂没有定义任何方法

public interface HierarchicalBeanFactory extends BeanFactory {
}

ListableBeanFactory:此接口定义了根据传进来的类进行比对bean的方法getBeansOfType(),返回注册表中所有的bean名称getBeanDefinitionNames();

// ListableBeanFactory定义了
// 1.根据指定类获取其有关系的类,2.获取所有BeanDefinition容器里的bean名称
public interface ListableBeanFactory extends BeanFactory {
    // 此方法主要是为了区分哪些是自定义类,这样后续就可将自定义类方法调用即可达到想要的目的
    // 从左往右,第一个T标识<T>是泛型
    //         第二个T是返回Map<String,T>
    //         第三个T是参数控制为泛型
    <T> Map<String, T> getBeansOfType(Class<T> type);

    // 返回注册表中所有的bean名称
    String[] getBeanDefinitionNames();
}

ConfigurableBeanFactory:继承HierarchicalBeanFactory接口,定义了addBeanPostProcessor()方法用来添加后置bean处理

所在包:beans.factory.config

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

}

AutowireCapableBeanFactory:定义两个方法applyBeanPostProcessorsBeforeInitialization()和applyBeanPostProcessorsAfterInitialization(),供后面实现此方法

public interface AutowireCapableBeanFactory extends BeanFactory {

    /*
     执行BeanPostProcessor接口实现类的postProcessBeforeInitial方法
     * */
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName);


    /*
    执行BeanPostProcessor接口实现类的postProcessAfterInitialization方法
    * */
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName);
}

ConfigurableListableBeanFactory:此接口继承了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory ,定义了getBeanDefinition()、preInstantiateSingletons()、addBeanPostProcessor();

preInstantiateSingletons方法和addBeanPostProcessor()这两个方法在应用上下文刷新时会调用,具体的实现则在beanFactory的某个子类实现

所在包:beans.factory

/*
 ConfigurableListableBeanFactory定义了:
 1.根据bean名称获取BeanDefinition数据方法
 2.preInstantiateSingletons()实现创建bean并存储单例bean方法
 3.添加BeanPostProcessor到集合中的方法
 并继承了ListableBeanFactory,AutowireCapableBeanFactory
 **/
public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
    // 此方法是在创建bean时需要先获取BeanDefinition时使用
    BeanDefination getBeanDefinition(String beanName);

    // 此方法是自定义实例化完,需要将某些对象更改的对象进行实例化
    void preInstantiateSingletons();

    // 此方法是在自定义类都实例化完毕,开始存储BeanPostProcessor到集合中
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

}

2.4 之前存在类修改点

AbstractAutowireCapableBeanFactory:此类修改为实现AutowireCapableBeanFactory,在创建Bean示例后添加进行后置处理方法initialization();

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
        Object bean = null;
        try {
            bean = createBeanInstance(beanDefinition, beanName, args);
            // 给 Bean 填充属性
            applyPropertyValues(beanName, bean, beanDefinition);
            // 执行bean的初始化方法和BeanPostProcessor的前置和后置处理方法。(都是用户自定义的哦)
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Instantiation of bean failed", e);
        }

        addSingleton(beanName, bean);
        return bean;
    }

    protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
        Constructor constructorToUse = null;
        Class<?> beanClass = beanDefinition.getBeanClass();
        Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
        for (Constructor ctor : declaredConstructors) {
            if (null != args && ctor.getParameterTypes().length == args.length) {
                constructorToUse = ctor;
                break;
            }
        }
        return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
    }

    /**
     * Bean 属性填充
     */
    protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
        try {
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {

                String name = propertyValue.getName();
                Object value = propertyValue.getValue();
                // 如遇到bean的引用,继续递归做bean的创建或者获取bean操作
                if (value instanceof BeanReference) {
                    // A 依赖 B,获取 B 的实例化
                    BeanReference beanReference = (BeanReference) value;
                    value = getBean(beanReference.getBeanName());
                }
                // 给bean对象属性填充
                BeanUtil.setFieldValue(bean, name, value);
            }
        } catch (Exception e) {
            throw new BeansException("Error setting property values:" + beanName);
        }
    }

    public InstantiationStrategy getInstantiationStrategy() {
        return instantiationStrategy;
    }

    public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
        this.instantiationStrategy = instantiationStrategy;
    }

    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
        // 1. 执行 BeanPostProcessor Before 处理
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        // 待完成内容:invokeInitMethods(beanName, wrappedBean, beanDefinition);
        invokeInitMethods(beanName, wrappedBean, beanDefinition);

        // 2. 执行 BeanPostProcessor After 处理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        return wrappedBean;
    }

    private void invokeInitMethods(String beanName, Object wrappedBean, BeanDefinition beanDefinition) {

    }

    // 调用实例化后修改Bean对象方法
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }

}

AbstractBeanFactory:AbstractBeanFactory由原来的实现BeanFactry修改为实现ConfigurableBeanFactory,AbstractBeanFactory类的修改添加了list的全局变量,实现了addBeanPostProcessor()方法。

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

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        this.beanPostProcessors.remove(beanPostProcessor);
        this.beanPostProcessors.add(beanPostProcessor);
    }

    public List<BeanPostProcessor> getBeanPostProcessors() {
        return this.beanPostProcessors;
    }

DefaultListableBeanFactory:此类更改为添加一个实现ConfigurableListableBeanFactory接口,所以将接口里的定义方法实现,并添加如下方法

    // 将bean定义数据循环取出并调用getBean方法,没被实例化则进行实例化
    @Override
    public void preInstantiateSingletons() throws BeansException {
        // jdk8新引入的运算符-双冒号的用法,这里beanDefinitionMap.keySet()是getBean()的参数
        beanDefinitionMap.keySet().forEach(this::getBean);
    }

    // 根据类的类型获取相关联的类信息
    @Override
    public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
        Map<String, T> result = new HashMap<>();
        // xml解析出来就放入beanDefinitionMap里,此时从beanDefinitionMap就可以找到需要的类
        beanDefinitionMap.forEach((beanName, beanDefnition) -> {
            Class beanClass = beanDefnition.getBeanClass();
            // isAssignableFrom是判断两个类之间关系的,不是实例对象关系,是本身类,是超类,是子类,是接口类通通都是true
            if (type.isAssignableFrom(beanClass)) {
                // 获取bean
                result.put(beanName, (T) getBean(beanName));
            }
        });
        return result;
    }

    @Override
    public String[] getBeanDefinitionNames() {
        return beanDefinitionMap.keySet().toArray(new String[0]);
    }

3.测试

3.1 事先准备工作

添加userDao,添加模拟根据id查询数据

public class UserDao {

    private static Map<String, String> hashMap = new HashMap<>();

   static {
        hashMap.put("10001", "hahaha");
        hashMap.put("10002", "ss");
        hashMap.put("10003", "sio");
    }

    public String queryUserName(String uId) {
        return hashMap.get(uId);
    }

}

UserService:添加UserService类,省略set,get,你们自行添加就好,然后模拟现实service调用Dao里的方法

public class UserService {

    private String uId;
    private String company;
    private String location;
    private UserDao userDao;

    public void queryUserInfo() {
         System.out.println("查询用户信息:" + userDao.queryUserName(uId)
                +",公司名称:"+company+",地址:"+location);
    }

    // ...get/set
}

3.2 添加前置后置自定义处理方法

MyBeanFactoryPostProcessor:实现BeanFactoryPostProcessor接口,也就实现了这个方法,因为是实例化之前修改,所以需要取出BeanDefination数据直接修改了

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
        PropertyValues propertyValues = beanDefinition.getPropertyValues();

        propertyValues.addPropertyValue(new PropertyValue("company", "字节跳动"));

    }
}

MyBeanPostProcessor:实现BeanPostProcessor接口,因为是已经被实例化了可以直接拿实例化后的对象进行修改。

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        if ("userService".equals(beanName)) {
            UserService userService = (UserService) bean;
            userService.setLocation("改为:北京");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

3.3 配置文件

添加自定义修改的配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean id="userDao" class="com.spring.sourcecode.springframework.test.UserDao"></bean>
    <bean id="userService" class="com.spring.sourcecode.springframework.test.UserService">
        <property name="uId" value="10001"></property>
        <property name="company" value="腾讯"></property>
        <property name="location" value="深圳"></property>
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean class="com.spring.sourcecode.springframework.beanhadel.MyBeanPostProcessor"></bean>
    <bean class="com.spring.sourcecode.springframework.beanhadel.MyBeanFactoryPostProcessor"></bean>
</beans>

在测试的时候使用上下文类去操作,ClassPathXmlApplicationContext,然后就可以简化操作了

 @Test
    public void test_xml() {
        // 1.初始化BeanFactory
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("classpath:spring.xml");

        // 2.获取bean对象调用方法
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.queryUserInfo();
    }

既用了上下文去进行bean的操作,又加入了Bean的前置和后置操作。测试结果如下图

 码字不易,点拨关注,点赞再走呗!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值