Blog: bugstack.cn

Precipitation, share, grow, let yourself and others can gain something! 😄

directory

  • Chapter 1:Introduction, I will take you to Spring!
  • Chapter 2:Try to achieve a simple Bean container
  • Chapter 3:Initial skill, the use of design pattern, the implementation of Bean definition, registration, access
  • Chapter 4:Budding class instantiation strategy with constructors based on Cglib
  • Chapter 5:A blockbuster feature implementation for injecting properties into Bean objects and relying on beans
  • Chapter 6:Design and implement resource loaders that parse and register Bean objects from spring.xml
  • Chapter 7:Invincible, application context, automatic identification, resource loading, extension mechanism
  • Chapter 8: To be filed…

One, foreword

You this code, can't write dead ah!

According to the experience of project landing, when we undertake urgent product needs, we usually choose to expand the existing similar projects. If there is no reserve of relevant projects, we may choose to temporarily build a project to meet product needs. However, at this time, we will encounter very practical problems. The complete design and development may not be able to meet the launch time, and the temporary completion requirements may not be able to respond to the temporary adjustment of the product after the launch.

What are the adjustments after the launch? As soon as the project went online, the operation was less than half a day, but the boss found that his activities seemed to be configured with too small amount of money, so the users did not come and could not cut leek. Hurriedly contact products in the middle of the night, come to come, you give me this change, that repair, the per capita discount of 10 thousand yuan put greatly, the possible two words to reduce in the back. Then adjust the preferential bonus pool configuration from 10 yuan to 11 yuan, quickly, quickly modify, you modify we can earn 100 million!!

Good guy, the project is a pile of temporary development, no background system, no configuration center, no module split, the boss made a few changes, the product to convey the urge, and finally the blame can be r & D. You can’t write this dead, this preferential configuration has to take out, this copy also background issue, this interface into the parameter also write dead, and then write a new interface! A fierce operation such as tiger, R & D brick repair interface, operation toss for several nights, finally PV150!

No matter what the business, product or operation is, as far as the research and development itself is concerned, it should try its best not to pile up a service temporarily, especially in the early stage of team building or when the operation idea is often adjusted, more attention should be paid to the design details and implementation scheme. Even if you ask for a risk extension, don’t put yourself on the hook for a job you know is a bad job.

In this chapter, the code is not written to death, because we need to continue to extend new functions in the handwritten Spring framework, such as the definition and instantiation of a Bean process, whether we can meet the need to customize the extension, the Bean object to perform some modification, enhancement, record and other operations? This process is basically some middleware extension development that you do when using the Spring container framework.

Second, the target

If you’ve developed spring-based technology components in your own work, or learned about SpringBoot middleware design and development, etc. You must inherit or implement the classes or interfaces exposed by Spring, get the BeanFactory and Bean object in the implementation of the interface, and do something with them, such as: Modify the Bean information, add log printing, handle database routing to the data source switch, connect the RPC service to the registry, etc.

Add Bean in the container on the instantiation of extension mechanism at the same time, also need to now about Spring. The XML initialization and loading strategy is optimized, because we are not likely to let the Spring itself development DefaultListableBeanFactory service oriented, Give it directly to the user. Modification points are as follows:

  • DefaultListableBeanFactory, XmlBeanDefinitionReader, are we in the Spring framework for service the use of functional test. It is a good example of how Spring loads XML and registers Bean objects, but this approach is spring-oriented and not yet extensible.
  • We now need to provide a way to extend Bean objects during Bean initialization, which is difficult to automate. So we need to integrate the Bean object extension mechanism functionality with the packaging of the Spring framework context to provide a complete service externally.

Three, the design

In order to be satisfied with performing user custom operations on Bean objects from registration to instantiation, interface classes need to be inserted in the Bean definition and initialization process, and this interface then implements the required services externally. This, combined with the ability to handle the Context of the Spring framework, meets our target requirements. The overall design structure is as follows:

  • The two interfaces that are satisfied with extending Bean objects are actually two of the most heavyweight interfaces in the Spring framework:BeanFactoryPostProcess å’Œ BeanPostProcessorAnd almost everyone is using the Spring framework to add two additional necessary interfaces to develop their own build requirements.
  • BeanFactoryPostProcessor (BeanFactoryPostProcessor) is a container extension mechanism provided by Spring framework components that allows you to define information about Bean objects after they are registered but before they are instantiatedBeanDefinitionPerform the modification operation.
  • BeanPostProcessor is also an extension mechanism provided by Spring, but BeanPostProcessor modifies Bean objects after they are instantiated and can also replace Bean objects. This section is closely related to the AOP that will be implemented later.
  • At the same time, if you just add these two interfaces without any packaging, then it is very troublesome for users. We want to develop Spring’s context-manipulation classes to incorporate XML loading, registration, instantiation, and additional modifications and extensions so that Spring can automatically scan our new services for easy use by users.

Four, implementation,

1. Engineering structure

small-spring-step-06└ ─ ─ the SRC ├ ─ ─ the main │ └ ─ ─ Java │ └ ─ ─ cn. Bugstack. Springframework │ ├ ─ ─ beans │ │ ├ ─ ─ factory │ │ │ ├ ─ ─ factory │ │ │ │ ├ ─ ─ AutowireCapableBeanFactory. Java │ │ │ │ ├ ─ ─ BeanDefinition. Java │ │ │ │ ├ ─ ─ spring 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 │ │ │ ├ ─ ─ The BeanFactory. Java │ │ │ ├ ─ ─ ConfigurableListableBeanFactory. Java │ │ │ ├ ─ ─ HierarchicalBeanFactory. Java │ │ │ └ ─ ─ ListableBeanFactory. Java │ │ ├ ─ ─ BeansException. Java │ │ ├ ─ ─ PropertyValue. Java │ │ └ ─ ─ PropertyValues. Java │ ├ ─ ─ The context │ │ ├ ─ ─ support │ │ │ ├ ─ ─ AbstractApplicationContext. Java │ │ │ ├ ─ ─ AbstractRefreshableApplicationContext. Java │ │ │ ├ ─ ─ AbstractXmlApplicationContext. Java │ │ │ └ ─ ─ ClassPathXmlApplicationContext. Java │ │ ├ ─ ─ ApplicationContext. Java │ │ └ ─ ─ ConfigurableApplicationContext. Java │ ├ ─ ─ core. IO │ │ ├ ─ ─ ClassPathResource. Java │ │ ├ ─ ─ DefaultResourceLoader. Java │ │ ├ ─ ─ FileSystemResource. Java │ │ ├ ─ ─ the Resource. The Java │ │ ├ ─ ─ ResourceLoader. Java │ │ └ ─ ─ UrlResource. Java │ └ ─ ─ utils │ └ ─ ─ ClassUtils. Java └ ─ ─ the test └ ─ ─ Java └ ─ ─ cn. Bugstack. Springframework. Test ├ ─ ─ bean │ ├ ─ ─ UserDao. Java │ └ ─ ─ UserService. Java ├ ─ ─ common │ ├ ─ ─ MyBeanFactoryPostProcessor. Java │ └ ─ ─ MyBeanPostProcessor. Java └ ─ ─  ApiTest.javaCopy the code

Project source: public account “bugStack wormhole stack”, reply: Spring column, get the full source code

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

  • In the whole class diagram is mainly about the Spring application context and the implementation of the Bean object extension mechanism.
  • Start with the ApplicationContext interface, which inherits the ListableBeanFactory interface, extend a series of abstract implementation classes for the ApplicationContext, and finishClassPathXmlApplicationContextClass implementation. This class is the one that is finally handed to the user.
  • At the same time, in the process of realizing the application context, by defining the interface:BeanFactoryPostProcessor,BeanPostProcessorTwo interfaces that concatenate mechanisms for extending beans.

2. Define spring BeanFactoryPostProcessor

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

public interface BeanFactoryPostProcessor {

    /** * Provide a mechanism to modify BeanDefinition properties ** after all BeanDefinitions have been loaded and before the Bean object is instantiated@param beanFactory
     * @throws BeansException
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
Copy the code
  • There is a description in the Spring source codeAllows for custom modification of an application context's bean definitions,adapting the bean property values of the context's underlying bean factory.This interface is content to provide a mechanism for modifying BeanDefinition properties after all beanDefinitions have been loaded and before the Bean object is instantiated.

3. The BeanPostProcessor defined

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

public interface BeanPostProcessor {

    /** * Executes this method ** before the Bean object executes the initialization method@param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /** * Executes this method ** after the Bean object executes the initialization method@param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
Copy the code
  • There is a description in the Spring source codeFactory hook that allows for custom modification of new bean instances,e.g. checking for marker interfaces or wrapping them with proxies.That is, it provides extension points to modify newly instantiated Bean objects.
  • In addition, this interface provides two methods:postProcessBeforeInitializationUsed to execute this method before the Bean object executes the initialization method,postProcessAfterInitializationUsed to execute the Bean object after the initialization method has been executed.

4. Define the context interface

cn.bugstack.springframework.context.ApplicationContext

public interface ApplicationContext extends ListableBeanFactory {}Copy the code
  • Context is a new service package to implement the application context function
  • ApplicationContext, which inherits from ListableBeanFactory, inherits from BeanFactory methods, such as some getBean methods. The ApplicationContext itself is the Central interface, but there is no need to add fetching ids and superclass contexts, so there is no definition of interface methods.

cn.bugstack.springframework.context.ConfigurableApplicationContext

public interface ConfigurableApplicationContext extends ApplicationContext {

    /** * refresh the container **@throws BeansException
     */
    void refresh(a) throws BeansException;

}
Copy the code
  • ConfigurableApplicationContext inherited from ApplicationContext, and provides a way to refresh the core.If you’ve looked at some Spring source code, you’ve probably seen this method.The next step is to refresh the container in the context implementation.

5. Application context abstract class implementation

cn.bugstack.springframework.context.support.AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    @Override
    public void refresh(a) throws BeansException {
        // 1. Create BeanFactory and load BeanDefinition
        refreshBeanFactory();

        // 2. Get BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        BeanFactoryPostProcessor (Invoke Factory Registered as beans in the context.)
        invokeBeanFactoryPostProcessors(beanFactory);

        // 4. BeanPostProcessor needs to register before other Bean objects are instantiated
        registerBeanPostProcessors(beanFactory);

        // 5. Instantiate the singleton Bean object in advance
        beanFactory.preInstantiateSingletons();
    }

    protected abstract void refreshBeanFactory(a) throws BeansException;

    protected abstract ConfigurableListableBeanFactory getBeanFactory(a);

    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 methods

}
Copy the code
  • AbstractApplicationContext DefaultResourceLoader inheritance is to deal withspring.xmlConfigure resource loading.
  • After that, you define the implementation process in Refresh (), including:
      1. Create a BeanFactory and load the BeanDefinition
      1. To obtain the BeanFactory
      1. Before the Bean is instantiated, execute BeanFactoryPostProcessor (Invoke Factory Processors registered as beans in the context.)
      1. The BeanPostProcessor needs to register before the other Bean objects are instantiated
      1. Instantiate the singleton Bean object ahead of time
  • In addition, the defined abstract methods, refreshBeanFactory() and getBeanFactory(), are implemented by other abstract classes that inherit this abstract class.

6. Get the Bean factory and load the resource

cn.bugstack.springframework.context.support.AbstractRefreshableApplicationContext

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

    private DefaultListableBeanFactory beanFactory;

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

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

    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);

    @Override
    protected ConfigurableListableBeanFactory getBeanFactory(a) {
        returnbeanFactory; }}Copy the code
  • In refreshBeanFactory(), this is mainly caughtDefaultListableBeanFactoryInstantiate and load the resource configurationloadBeanDefinitions(beanFactory)After loading, you can complete the definition and registration of Bean objects in the spring. XML configuration file, including the configuration Bean information that implements interfaces BeanFactoryPostProcessor and BeanPostProcessor.
  • At this point, however, resource loading only defines an abstract class methodloadBeanDefinitions(DefaultListableBeanFactory beanFactory)Continues to be implemented by other abstract classes.

7. Load the configuration information in the 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();

}
Copy the code
  • In AbstractXmlApplicationContext loadBeanDefinitions methods of an abstract class implementation, using XmlBeanDefinitionReader class, the operation of processing the information about the XML file configuration.
  • It also leaves behind an abstract class method, getConfigLocations(), which gets 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(a) {}/** * Load the BeanDefinition from XML and refresh the context **@param configLocations
     * @throws BeansException
     */
    public ClassPathXmlApplicationContext(String configLocations) throws BeansException {
        this(new String[]{configLocations});
    }

    /** * Load the BeanDefinition from XML and refresh the context *@param configLocations
     * @throws BeansException
     */
    public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
        this.configLocations = configLocations;
        refresh();
    }

    @Override
    protected String[] getConfigLocations() {
        returnconfigLocations; }}Copy the code
  • ClassPathXmlApplicationContext, is a specific foreign provide users with context method.
  • In the inherited AbstractXmlApplicationContext and a separation of layers of the function of the abstract class after implementation, in the implementation of such ClassPathXmlApplicationContext is simpler, It mainly calls methods in an inherited abstract class and provides configuration file address information.

9. Complete pre – and post-processing at Bean creation time

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);
            // Populate the Bean with properties
            applyPropertyValues(beanName, bean, beanDefinition);
            // Executes the Bean initialization methods and the BeanPostProcessor pre - and post-processing methods
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Instantiation of bean failed", e);
        }

        addSingleton(beanName, bean);
        return bean;
    }

    public InstantiationStrategy getInstantiationStrategy(a) {
        return instantiationStrategy;
    }

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

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

        // invokeInitMethods(beanName, wrappedBean, beanDefinition);
        invokeInitMethods(beanName, wrappedBean, beanDefinition);

        // 2. Run the BeanPostProcessor After command
        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;
        }
        returnresult; }}Copy the code
  • After implementing the BeanPostProcessor interface, there are two interface methods involved,postProcessBeforeInitialization,postProcessAfterInitialization, respectively, for additional processing before and after the Bean object is initialized.
  • That is, you need to add it in the createBean method when you create the Bean objectinitializeBean(beanName, bean, beanDefinition);Operation. And this operation is primarily primarily for methodsapplyBeanPostProcessorsBeforeInitialization,applyBeanPostProcessorsAfterInitializationThe use of.
  • Also need to mention applyBeanPostProcessorsBeforeInitialization, applyBeanPostProcessorsAfterInitialization two methods is the interface classAutowireCapableBeanFactoryA new addition.

Five, the test

1. Prepare

cn.bugstack.springframework.test.bean.UserDao

public class UserDao {

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

    static {
        hashMap.put("10001".Little Fuge.);
        hashMap.put("10002"."Eight glasses of water");
        hashMap.put("10003"."Will");
    }

    public String queryUserName(String uId) {
        returnhashMap.get(uId); }}Copy the code

cn.bugstack.springframework.test.bean.UserService

public class UserService {

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

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

    / /... get/set
}
Copy the code
  • Dao and Service are common development scenarios. Inject the UserDao into the UserService so that the Bean property dependencies are reflected.
  • In addition, company and location are added to test the function of BeanPostProcessor and BeanFactoryPostProcessor interfaces on Bean attribute information extension.

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"."Change to: Bytedance")); }}Copy the code

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("Change to: Beijing");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        returnbean; }}Copy the code
  • If you’ve done some component development in Spring, you’ll be familiar with these two classes, and the tests in this article implement both classes to do something with Bean objects during instantiation.

3. Configuration file

Basic configuration, no BeanFactoryPostProcessor, BeanPostProcessor, and implementation class


      
<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="Tencent"/>
        <property name="location" value="Shenzhen"/>
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>
Copy the code

Enhanced configuration, BeanFactoryPostProcessor, BeanPostProcessor, implementation classes


      
<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="Tencent"/>
        <property name="location" value="Shenzhen"/>
        <property name="userDao" ref="userDao"/>
    </bean>

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

</beans>
Copy the code
  • There are two configuration files provided here, one that does not contain BeanFactoryPostProcessor and BeanPostProcessor, and the other that does. The main reason for this configuration is to verify how it works when using Spring’s new application context and when not using it.

4. No application context

@Test
public void test_BeanFactoryPostProcessorAndBeanPostProcessor(a){
    1. Initialize the BeanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    // 2. Read config file & register Bean
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    reader.loadBeanDefinitions("classpath:spring.xml");

    // 3. BeanDefinition property values are modified after the BeanDefinition is loaded and before the &bean is instantiated
    MyBeanFactoryPostProcessor beanFactoryPostProcessor = new MyBeanFactoryPostProcessor();
    beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);

    // 4. After the Bean is instantiated, modify the Bean property information
    MyBeanPostProcessor beanPostProcessor = new MyBeanPostProcessor();
    beanFactory.addBeanPostProcessor(beanPostProcessor);

    // 5. Get the Bean object to call the method
    UserService userService = beanFactory.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("Test Results:" + result);
}
Copy the code
  • The beanFactory DefaultListableBeanFactory created and used XmlBeanDefinitionReader loading configuration file, or familiar with.
  • The next step is to MyBeanFactoryPostProcessor and MyBeanPostProcessor processing, one is before BeanDefinition loaded & Bean instantiation, modify BeanDefinition attribute values, The other is to modify the Bean property information after the Bean is instantiated.

The test results

Test result: Xiaofuge, changed: Bytedance, changed: Beijing Process finished with exit code0
Copy the code
  • As you can see from the test results, the property information we configured is different from that in the spring.xml configuration file.

5. Use the application context

@Test
public void test_xml(a) {
    1. Initialize the BeanFactory
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml");

    // 2. Get the Bean object to call the method
    UserService userService = applicationContext.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("Test Results:" + result);
}
Copy the code
  • In addition to use new ClassPathXmlApplicationContext application context class, then it’s much more convenient to operate,This is the user-oriented classHere, can give ClassPathXmlApplicationContext configuration file, also do not need to manage some custom implementations of Spring interface classes.

The test results

Test result: Xiaofuge, changed: Bytedance, changed: Beijing Process finished with exit code0
Copy the code
  • This is the same as testing without the application context, but in a more convenient way.

Six, summarized

  • In this paper, we add BeanFactoryPostProcess and BeanPostProcessor, two very important interfaces in Spring framework, as well as the implementation of application context. The ApplicationContext interface is defined as an extension of the BeanFactory interface. It can be used for automatic identification, resource loading, container events, listeners, etc. Some internationalization support, singleton Bean automatic initialization, etc., can be implemented and extended in this class.
  • Through the implementation of this article, I am sure to have a good understanding of BeanFactoryPostProcess and BeanPostProcessor. In the future development of Spring middleware, if you need to obtain Bean objects and modify some attribute information, Then you can use both interfaces. At the same time, BeanPostProcessor is also the key to implement AOP cutting technology.
  • Someone asked:You ask a lot of questions in an interview, but you don't need them in the job.Ga ha yao, that you say you drive on the bridge, will every time hit both sides of the guardrail, do not hit is, that do not repair wow, directly spread a flat plate, but also save the material. In fact, learning the principles of core technologies is more helpful for you to complete more complex architecture design. When your knowledge can more comprehensively cover the requirements undertaken, you will be better able to make reasonable architecture and implementation.

Seven, series recommendation

  • Small fu ge, a “sideline” code farmers!
  • For a long time, Little Fuge’s “Relearning Java Design Pattern” has finally been published, color printing & paper!
  • Half a year recruitment screening 400+ resume, tell you how to write easy to be flirted!
  • A code review, almost failed the trial period!
  • College four years to graduation work 5 years of learning route resources summary