Handwritten Spring Config, the final battle, come and see!

Configuration Analysis

Why provide a configuration method? In the previous content, we tested it through code:

GeneralBeanDefinition bd = new GeneralBeanDefinition();
bd.setBeanClass(Lad.class);
List<Object> args = new ArrayList<>();
args.add("sunwukong");
args.add(new BeanReference("magicGril"));
bd.setConstructorArgumentValues(args);
bf.registerBeanDefinition("swk", bd);

bd = new GeneralBeanDefinition();
bd.setBeanClass(MagicGril.class);
args = new ArrayList<>();
args.add("baigujing");
bd.setConstructorArgumentValues(args);
bf.registerBeanDefinition("magicGril", bd);

Let's take a look at what the configuration looks like when it is usually used:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="girl" class="di.MagicGirl"
     init-method="start" destroy-method="end">
        <constructor-arg type="java.lang.String" value="girl"></constructor-arg>
        <property name="friend" ref="boy"></property>
    </bean>

    <bean id="boy" class="di.Lad">
        <constructor-arg type="java.lang.String" value="boy"></constructor-arg>
        <constructor-arg type="di.MagicGirl" value="girl"></constructor-arg>
    </bean>
</beans>

It can be seen that the advantages of the way of providing configuration:

  • Practical and simple, more flexible to change
  • without changing the code

The commonly used configuration methods are in the form of XML and annotations. Their working process is as follows:

image.png

Configuration work process

Defining XML tags and annotations

What XML tags and annotations need to be defined? Knowing from the previous content, the content of the configuration is the Bean definition information, then the content of the Bean definition is the content that needs to be configured

First, let's take a look at what information is in the Bean definition interface:

image.png

In the XML configuration method, you first need to define a DTD or XSD document to define a set of tag information to specify the Bean definition

<bean id="girl" class="di.MagicGirl"
     init-method="start" destroy-method="end">
        <constructor-arg type="java.lang.String" value="girl"></constructor-arg>
        <property name="friend" ref="boy"></property>
</bean>

It can be seen that the content specified by the bean configuration is the information in the bean definition interface

In the way of annotation, a set of annotations needs to be defined, so which annotations are needed, which is also the content of the Bean definition interface:

  • Specifying the class, specifying the BeanName, specifying the scope, specifying the factory method, specifying the factory bean, specifying the init method, specifying the destroy method, these are implemented through @Component when we use Spring
  • Specifying dependencies on construction parameters: @Autowired, @Qualifier
  • Specify property dependencies: @Value

Analysis of Bean Configuration

The parsing process of Bean configuration needs to be implemented by a separate interface, not in the BeanFactory. To achieve the principle of single responsibility, it is necessary to define a separate interface to parse the Bean configuration, and then register the Bean definition with the BeanFactory

ApplicationContext interface

The ApplicationContext interface is used to complete the Bean configuration parsing. As mentioned above, there are XML and annotations for implementing the configuration, so there will be two implementation classes to implement the ApplicationContext interface.

image.png

  1. Implementation in XML:
  • There may be multiple XML files, so list is used here
  • Need to complete: the tasks of loading xml, parsing xml, creating bean definitions, and registering bean definitions
  1. Implementation of Annotation
  • There will also be multiple scanned packages, and list is also used here
  • Need to complete: scan packages, get annotations, create bean definitions, and register bean definitions.

Because Bean definitions need to be created and registered, the BeanFactory and BeanDefinitionRegistry interfaces will be used, so this part of the code will be repeated if implemented separately in the subclass, so it is abstracted and placed in the parent class:

image.png

What interfaces and classes do users need to know when using them?

  1. Specify configuration related: xml, annotations
  2. Get bean related: BeanFactory

Then you can use the appearance mode, so that the user only needs to know the ApplicationContext and its subclasses. The ApplicationContext can inherit the BeanFactory, and then combine the two interfaces:

image.png

ApplicationContext interface:

/**
 * @className: ApplicationContext
 * 用来构建整个应用环境的接口,用来完成Bean的配置和解析
 * 1:为了减少用户对框架类接口的依赖,扩展了BeanFactory接口,
 * Bean的配置和Bean的获取都可以通过ApplicationContext接口来完成
 * 2:配置资源的方式有xml和注解,所以存在xml和注解两种子类的实现
 * 3. Bean配置解析首先需要加载,所以实现了配置资源Resource的加载接口ResourceLoader
 * @author: TR
 */
public interface ApplicationContext extends ResourceLoader,BeanFactory {

}

Abstract class implementation of ApplicationContext

/**
 * @className: AbstractApplicationContext
 * @description: ApplicationContext的抽象类实现
 * @author: TR
 */
public abstract class AbstractApplicationContext implements ApplicationContext {

    /** 用组合的方式来持有BeanFactory,完成BeanFactory接口的方法 */
    protected BeanFactory beanFactory;

    public AbstractApplicationContext() {
        super();
        this.beanFactory = new PreBuildBeanFactory();
    }

    public AbstractApplicationContext(BeanFactory beanFactory) {
        super();
        this.beanFactory = beanFactory;
    }

    @Override
    public Object getBean(String beanName) throws Exception {
        return this.beanFactory.getBean(beanName);
    }

    @Override
    public void registerBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        this.beanFactory.registerBeanPostProcessor(beanPostProcessor);
    }
}

ApplicationContext implementation class of xml configuration

/**
 * @className: XmlApplicationContext
 * @description: xml配置方式的ApplicationContext实现类
 * @author: TR
 */
public class XmlApplicationContext extends AbstractApplicationContext {

}

ApplicationContext implementation class of annotation configuration

/**
 * @className: AnnotationApplicationContext
 * @description: 注解配置方式的ApplicationContext实现类
 * @author: TR
 */
public class AnnotationApplicationContext extends AbstractApplicationContext {

}

Guess you like

Origin blog.csdn.net/qq_41701956/article/details/118159022