2
头图

Author: Xiao Fu Ge
Blog: https://bugstack.cn

Precipitate, share, and grow, so that you and others can gain something! 😄

table of Contents

I. Introduction

Your code can't be written dead!

According to the project landing experience, when we undertake urgent product requirements, we usually choose to expand in the original similar projects. If there is no reserve for related types of projects, we may also choose to build a temporary project to realize the product demand. But at this time, you will encounter very real problems. Choosing a complete design and development may not meet the launch time, and the improvised completion requirements may not have temporary adjustments to respond to the product after launch.

What are the adjustments after going online? As soon as the project went live, and it had been in operation for less than half a day, the boss found that his configuration activities seemed to be too small, and the users were not coming, so he couldn't cut the leeks. Hurry up to contact the product in the middle of the night, come and come, you will change this, and repair it, enlarge the per capita discount of 10,000 yuan, and put the word "possible" in the back. Then adjust the preferential bonus pool configuration from 10 yuan to 11 yuan, hurry up, quickly modify it, you can make 100 million! ! !

Good guy, the project was developed temporarily. There is no back-end system, no configuration center, and no module splitting. The boss changes every sentence, and the product is used to convey the urging. In the end, it is research and development. 160caacb3f2cbf, you can’t hard-coded this, this preferential configuration has to be extracted, this copy should also be issued in the background, this interface operation is as fierce as a tiger, the development of the brick and repair interface, the operation toss for several nights, and finally PV150!

Regardless of the business, product, or operation, as far as R&D is concerned, it is necessary to avoid temporarily stacking up a service as much as possible, especially in the early stage of team building or when the operation idea is frequently adjusted, more attention should be paid to design details and implementation Program. Even if you report a risk postponement, don't let yourself take a job that you know is a bad pit.

And this chapter said that does not write the code dead, it is because we need to continue to expand new functions in the handwritten Spring framework, such as the definition and instantiation of a Bean before and after the process, whether it can satisfy us for custom expansion, right Does the Bean object perform some operations such as modification, enhancement, recording, etc.? is basically the middleware extension development you do when you use the Spring container framework.

2. Goal

If you have developed Spring-based technical components in your actual work, or have learned about SpringBoot middleware design and development and so on. Then you must inherit or implement the classes or interfaces exposed by Spring, obtain the BeanFactory and the acquisition of Bean objects in the implementation of the interface, and do some operations on these contents, for example: modify the Bean information, add log printing , Process database routing to switch the data source, connect the registry to the RPC service, etc.

While adding an extension mechanism to the instantiation process of the Bean in the container, it is also necessary to optimize the current Spring.xml initialization and loading strategy, because we are unlikely to allow the DefaultListableBeanFactory service developed for Spring itself to be directly used by users. The modification points are as follows:

  • DefaultListableBeanFactory and XmlBeanDefinitionReader are the way we use the service function test in the current Spring framework. It can well reflect how Spring loads xml and registers the Bean object operation process, but this way is oriented to Spring itself. It does not yet have a certain degree of scalability.
  • Just as we now need to provide a way to complete the expansion of the Bean object during the Bean initialization process, it is difficult to automate the processing. Therefore, we must integrate the Bean object extension mechanism function and the packaging of the Spring framework context to provide a complete service to the outside world.

Three, design

In order to be satisfied with performing user-defined operations from registration to instantiation of the Bean object, it is necessary to insert an interface class during the definition and initialization of the Bean, and this interface can then be externally used to implement the services that you need. Then combined with the processing capabilities of the Spring framework context, we can meet our target needs. The overall design structure is as follows:

  • The two interfaces that are satisfied with the extension of the Bean object are actually two very heavyweight interfaces in the Spring framework: BeanFactoryPostProcess and BeanPostProcessor , which are almost two necessary interfaces for everyone using the Spring framework to add additional development requirements for their own formation. .
  • BeanFactoryPostProcessor, a container extension mechanism provided by the Spring framework, allows the Bean definition information BeanDefinition be modified after the Bean object is registered but before it is instantiated.
  • BeanPostProcessor is also an extension mechanism provided by Spring, but BeanPostProcessor modifies the Bean object after the Bean object is instantiated, and can also replace the Bean object. This part is closely related to the AOP to be implemented later.
  • At the same time, if you just add these two interfaces without any packaging, it is still very troublesome for users. We hope that in the development of Spring's context operation classes, the corresponding XML loading, registration, instantiation, and new modifications and extensions are integrated, so that Spring can automatically scan for our new services, which is convenient for users to use.

Fourth, realize

1. Engineering structure

small-spring-step-06
└── src
    ├── main
    │   └── java
    │       └── cn.bugstack.springframework
    │           ├── beans
    │           │   ├── factory
    │           │   │   ├── factory
    │           │   │   │   ├── AutowireCapableBeanFactory.java
    │           │   │   │   ├── BeanDefinition.java
    │           │   │   │   ├── BeanFactoryPostProcessor.java
    │           │   │   │   ├── BeanPostProcessor.java
    │           │   │   │   ├── BeanReference.java
    │           │   │   │   ├── ConfigurableBeanFactory.java
    │           │   │   │   └── SingletonBeanRegistry.java
    │           │   │   ├── support
    │           │   │   │   ├── AbstractAutowireCapableBeanFactory.java
    │           │   │   │   ├── AbstractBeanDefinitionReader.java
    │           │   │   │   ├── AbstractBeanFactory.java
    │           │   │   │   ├── BeanDefinitionReader.java
    │           │   │   │   ├── BeanDefinitionRegistry.java
    │           │   │   │   ├── CglibSubclassingInstantiationStrategy.java
    │           │   │   │   ├── DefaultListableBeanFactory.java
    │           │   │   │   ├── DefaultSingletonBeanRegistry.java
    │           │   │   │   ├── InstantiationStrategy.java
    │           │   │   │   └── SimpleInstantiationStrategy.java  
    │           │   │   ├── support
    │           │   │   │   └── XmlBeanDefinitionReader.java
    │           │   │   ├── BeanFactory.java
    │           │   │   ├── ConfigurableListableBeanFactory.java
    │           │   │   ├── HierarchicalBeanFactory.java
    │           │   │   └── ListableBeanFactory.java
    │           │   ├── BeansException.java
    │           │   ├── PropertyValue.java
    │           │   └── PropertyValues.java 
    │           ├── context
    │           │   ├── support
    │           │   │   ├── AbstractApplicationContext.java 
    │           │   │   ├── AbstractRefreshableApplicationContext.java 
    │           │   │   ├── AbstractXmlApplicationContext.java 
    │           │   │   └── ClassPathXmlApplicationContext.java 
    │           │   ├── ApplicationContext.java 
    │           │   └── ConfigurableApplicationContext.java
    │           ├── core.io
    │           │   ├── ClassPathResource.java 
    │           │   ├── DefaultResourceLoader.java 
    │           │   ├── FileSystemResource.java 
    │           │   ├── Resource.java 
    │           │   ├── ResourceLoader.java 
    │           │   └── UrlResource.java
    │           └── utils
    │               └── ClassUtils.java
    └── test
        └── java
            └── cn.bugstack.springframework.test
                ├── bean
                │   ├── UserDao.java
                │   └── UserService.java  
                ├── common
                │   ├── MyBeanFactoryPostProcessor.java
                │   └── MyBeanPostProcessor.java
                └── ApiTest.java

project source code : public account "bugstack wormhole stack", reply: Spring column, get the complete source code

The class relationship between Spring application context and Bean object extension mechanism, as shown in Figure 7-3

图 7-3

  • What is mainly reflected in the entire class diagram is about the Spring application context and the realization of the Bean object extension mechanism.
  • Starting with the ApplicationContext interface that inherited the ListableBeanFactory interface, a series of abstract implementation classes for application contexts were expanded, and finally the implementation of the ClassPathXmlApplicationContext class was completed. And this class is the class finally handed over to the user.
  • At the same time, in the process of implementing the application context, by defining BeanFactoryPostProcessor and BeanPostProcessor , the extension mechanism of the Bean is connected in series.

2. Define BeanFactoryPostProcessor

cn.bugstack.springframework.beans.factory.config.BeanFactoryPostProcessor

public interface BeanFactoryPostProcessor {

    /**
     * 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
     *
     * @param beanFactory
     * @throws BeansException
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
  • In the Spring source code, there is a description of Allows for custom modification of an application context's bean definitions,adapting the bean property values of the context's underlying bean factory. In fact, this interface is to provide a mechanism to modify the BeanDefinition properties after all the BeanDefinition is loaded and before the Bean object is instantiated.

3. Define BeanPostProcessor

cn.bugstack.springframework.beans.factory.config.BeanPostProcessor

public interface BeanPostProcessor {

    /**
     * 在 Bean 对象执行初始化方法之前,执行此方法
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * 在 Bean 对象执行初始化方法之后,执行此方法
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
  • In the Spring source code, there is a description of Factory hook that allows for custom modification of new bean instances,e.g. checking for marker interfaces or wrapping them with proxies. that provides extension points for modifying the newly instantiated Bean object.
  • In addition, this interface provides two methods: postProcessBeforeInitialization used to execute this method before the Bean object executes the initialization method, and postProcessAfterInitialization used to execute this method after the Bean object executes the initialization method.

4. Define the context interface

cn.bugstack.springframework.context.ApplicationContext

public interface ApplicationContext extends ListableBeanFactory {
}
  • context is a new service package that implements the application context function this time
  • ApplicationContext, which inherits from ListableBeanFactory, also inherits BeanFactory methods, such as some getBean methods. In addition, ApplicationContext itself is a Central interface, but there is no need to add some IDs and parent contexts, so there is no definition of interface methods for the time being.

cn.bugstack.springframework.context.ConfigurableApplicationContext

public interface ConfigurableApplicationContext extends ApplicationContext {

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

}
  • ConfigurableApplicationContext inherits from ApplicationContext and provides the core method of refresh. If you have seen some Spring source code, you will definitely see this method. also needs to complete the operation process of refreshing the container in the implementation of the context.

5. Application context abstract class implementation

cn.bugstack.springframework.context.support.AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    @Override
    public void refresh() throws BeansException {
        // 1. 创建 BeanFactory,并加载 BeanDefinition
        refreshBeanFactory();

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

        // 3. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
        invokeBeanFactoryPostProcessors(beanFactory);

        // 4. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
        registerBeanPostProcessors(beanFactory);

        // 5. 提前实例化单例Bean对象
        beanFactory.preInstantiateSingletons();
    }

    protected abstract void refreshBeanFactory() throws BeansException;

    protected abstract ConfigurableListableBeanFactory getBeanFactory();

    private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        }
    }

    private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        }
    }
    
    //... getBean、getBeansOfType、getBeanDefinitionNames 方法

}
  • AbstractApplicationContext inherits DefaultResourceLoader to handle the loading of spring.xml
  • After that, the implementation process is defined in refresh(), including:

      1. Create BeanFactory and load BeanDefinition
      1. Get BeanFactory
      1. Before the Bean is instantiated, execute BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
      1. BeanPostProcessor needs to perform the registration operation before the instantiation of other Bean objects
      1. Instantiate the singleton bean object in advance
  • In addition, the defined abstract methods, refreshBeanFactory() and getBeanFactory() are implemented by other abstract classes that inherit this abstract class.

6. Get Bean Factory and Load Resources

cn.bugstack.springframework.context.support.AbstractRefreshableApplicationContext

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

    private DefaultListableBeanFactory beanFactory;

    @Override
    protected void refreshBeanFactory() throws BeansException {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }

    private DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory();
    }

    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);

    @Override
    protected ConfigurableListableBeanFactory getBeanFactory() {
        return beanFactory;
    }

}
  • In refreshBeanFactory () is mainly acquired DefaultListableBeanFactory instantiation and loading operations on the resource allocation of loadBeanDefinitions(beanFactory) , to complete the definition and registration of spring.xml configuration file Bean object after loading is complete, but also includes implements the interface BeanFactoryPostProcessor , BeanPostProcessor configuration Bean information.
  • But at this time, resource loading only defines an abstract class method loadBeanDefinitions(DefaultListableBeanFactory beanFactory) , which continues to be inherited and implemented by other abstract classes.

7. Loading configuration information in context

cn.bugstack.springframework.context.support.AbstractXmlApplicationContext

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);
        String[] configLocations = getConfigLocations();
        if (null != configLocations){
            beanDefinitionReader.loadBeanDefinitions(configLocations);
        }
    }

    protected abstract String[] getConfigLocations();

}
  • In the implementation of the loadBeanDefinitions method of the AbstractXmlApplicationContext abstract class, the XmlBeanDefinitionReader class is used to handle the operations on the configuration information of the XML file.
  • At the same time, an abstract class method is left here, getConfigLocations(), this method is to get the address description of the configuration information from the entry context class.

8. Application context implementation class (ClassPathXmlApplicationContext)

cn.bugstack.springframework.context.support.ClassPathXmlApplicationContext

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {

    private String[] configLocations;

    public ClassPathXmlApplicationContext() {
    }

    /**
     * 从 XML 中加载 BeanDefinition,并刷新上下文
     *
     * @param configLocations
     * @throws BeansException
     */
    public ClassPathXmlApplicationContext(String configLocations) throws BeansException {
        this(new String[]{configLocations});
    }

    /**
     * 从 XML 中加载 BeanDefinition,并刷新上下文
     * @param configLocations
     * @throws BeansException
     */
    public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
        this.configLocations = configLocations;
        refresh();
    }

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

}
  • ClassPathXmlApplicationContext is a specific application context method provided to users.
  • After inheriting AbstractXmlApplicationContext and implementing separation of the functions of layers of abstract classes, the realization of this class of ClassPathXmlApplicationContext is much simpler, mainly for calling methods in inherited abstract classes and providing configuration file address information.

9. Complete the pre- and post-processing when the Bean is created

cn.bugstack.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

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;
    }

    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(bean, beanName);
        return wrappedBean;
    }

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

    }

    @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;
    }

}
  • After implementing the BeanPostProcessor interface, two interface methods are involved, postProcessBeforeInitialization and postProcessAfterInitialization , which act on the additional processing before and after the initialization of the Bean object.
  • initializeBean(beanName, bean, beanDefinition); operation in the createBean method when creating the Bean object. And this operation is mainly for the use of applyBeanPostProcessorsBeforeInitialization and applyBeanPostProcessorsAfterInitialization
  • Also need to mention, applyBeanPostProcessorsBeforeInitialization, applyBeanPostProcessorsAfterInitialization two methods are newly added AutowireCapableBeanFactory

Five, test

1. Prepare in advance

cn.bugstack.springframework.test.bean.UserDao

public class UserDao {

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

    static {
        hashMap.put("10001", "小傅哥");
        hashMap.put("10002", "八杯水");
        hashMap.put("10003", "阿毛");
    }

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

}

cn.bugstack.springframework.test.bean.UserService

public class UserService {

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

    public void queryUserInfo() {
        return userDao.queryUserName(uId);
    }

    // ...get/set
}
  • Dao and Service are the scenes we often use in our usual development. Inject UserDao into UserService, so that the dependency of Bean attributes can be reflected.
  • In addition, two new attribute information, company and location, are newly added here, which is convenient to test the effect of the two interfaces of BeanPostProcessor and BeanFactoryPostProcessor on the extension of Bean attribute information.

2. Implement BeanPostProcessor and BeanFactoryPostProcessor

cn.bugstack.springframework.test.common.MyBeanFactoryPostProcessor

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
        PropertyValues propertyValues = beanDefinition.getPropertyValues();

        propertyValues.addPropertyValue(new PropertyValue("company", "改为:字节跳动"));
    }

}

cn.bugstack.springframework.test.common.MyBeanPostProcessor

public class MyBeanPostProcessor implements BeanPostProcessor {

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

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

}
  • If you have done some component development in Spring, then you must be very familiar with these two classes. The test in this article also implements these two classes and does some operations on the Bean object in the instantiation process.

3. Configuration file

basic configuration, no BeanFactoryPostProcessor, BeanPostProcessor, implementation class

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="userDao" class="cn.bugstack.springframework.test.bean.UserDao"/>

    <bean id="userService" class="cn.bugstack.springframework.test.bean.UserService">
        <property name="uId" value="10001"/>
        <property name="company" value="腾讯"/>
        <property name="location" value="深圳"/>
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>

enhanced configuration, BeanFactoryPostProcessor, BeanPostProcessor, implementation class

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="userDao" class="cn.bugstack.springframework.test.bean.UserDao"/>

    <bean id="userService" class="cn.bugstack.springframework.test.bean.UserService">
        <property name="uId" value="10001"/>
        <property name="company" value="腾讯"/>
        <property name="location" value="深圳"/>
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean class="cn.bugstack.springframework.test.common.MyBeanPostProcessor"/>
    <bean class="cn.bugstack.springframework.test.common.MyBeanFactoryPostProcessor"/>

</beans>
  • Two configuration files are provided here, one does not include BeanFactoryPostProcessor, BeanPostProcessor, and the other is included. The reason for this configuration is mainly to compare and verify how to operate when using Spring's newly added application context and when not in use.

4. No application context

@Test
public void test_BeanFactoryPostProcessorAndBeanPostProcessor(){
    // 1.初始化 BeanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    // 2. 读取配置文件&注册Bean
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    reader.loadBeanDefinitions("classpath:spring.xml");

    // 3. BeanDefinition 加载完成 & Bean实例化之前,修改 BeanDefinition 的属性值
    MyBeanFactoryPostProcessor beanFactoryPostProcessor = new MyBeanFactoryPostProcessor();
    beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);

    // 4. Bean实例化之后,修改 Bean 属性信息
    MyBeanPostProcessor beanPostProcessor = new MyBeanPostProcessor();
    beanFactory.addBeanPostProcessor(beanPostProcessor);

    // 5. 获取Bean对象调用方法
    UserService userService = beanFactory.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("测试结果:" + result);
}
  • The way DefaultListableBeanFactory creates a beanFactory and uses XmlBeanDefinitionReader to load configuration files is relatively familiar.
  • The next step is the processing of MyBeanFactoryPostProcessor and MyBeanPostProcessor. One is to modify the attribute value of the BeanDefinition before the BeanDefinition is loaded and the Bean is instantiated, and the other is to modify the Bean attribute information after the Bean is instantiated.

test result

测试结果:小傅哥,改为:字节跳动,改为:北京

Process finished with exit code 0
  • Through the test results, we can see that the attribute information we configured is different from that in the spring.xml configuration file.

5. Use application context

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

    // 2. 获取Bean对象调用方法
    UserService userService = applicationContext.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("测试结果:" + result);
}
  • In addition, using the newly added ClassPathXmlApplicationContext application context class is much more convenient to operate. is the user-oriented class . Here you can hand over the configuration file to ClassPathXmlApplicationContext in one step, and you don’t need to manage some custom implementations of Spring. The class of the interface.

test result

测试结果:小傅哥,改为:字节跳动,改为:北京

Process finished with exit code 0
  • This is the same test result without application context, but the current method is more convenient.

Six, summary

  • This article mainly adds two very important interfaces BeanFactoryPostProcess and BeanPostProcessor in the Spring framework. At the same time, it also adds the implementation of application context. The definition of ApplicationContext interface is an interface that inherits the newly added functions of BeanFactory. It can be satisfied with automatic identification and resource loading. , Container events, listeners and other functions, such as some internationalization support, singleton bean automatic initialization, etc., can also be implemented and expanded in this class.
  • Through the implementation of this article, you will have a good understanding of BeanFactoryPostProcess and BeanPostProcessor. When doing some Spring middleware development in the future, if you need to obtain Bean objects and modify some attribute information, then you can use these two interfaces. At the same time, BeanPostProcessor is also the key to the realization of AOP aspect technology.
  • Someone asked: so many interview questions, but I don’t need it for work. Is it Gaha? , Gaha, then you said that when you drive on the bridge, you will hit the guardrails on both sides every time. Don't hit it, don't you want to repair it, just lay a slab and save materials. In fact, learning the principles of core technology is more helpful for you to complete more complex architecture design. When your knowledge can more fully cover the needs you undertake, you can also better make a reasonable architecture and landing.

Seven, series recommendation


小傅哥
4.7k 声望28.4k 粉丝

CodeGuide | 程序员编码指南 - 原创文章、案例源码、资料书籍、简历模版等下载。