The background,

Spring uses the BeanFactory, which is an implementation of the factory pattern, to generate and manage beans. The BeanFactory uses an inversion of control pattern to separate the application’s configuration and dependency specifications from the actual application code. The BeanFactory uses dependency injection to provide dependencies to components.

Second, preparation

Preparations: Run a Springboot project to create a new Springboot project. Since THE version I usually use is 2.1.3.RELEASE, I chose my own version. Using the Maven project, introduce the spring-boot-starter dependency package. OK, a simple environment is ready.

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> The < version > 2.1.3. RELEASE < / version > < / dependencyCopy the code
@SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); }}Copy the code

What are the ways to define a Bean?

3.1 @Component annotation mode

The default scan path of the startup class is the current directory and subdirectories. Just make sure to annotate @Component,@Service,@Configuration, etc. Spring will inject the Bean into the container, which is probably the most common method.

@Component public class MyCompBean { private String name="myCompBean"; } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //@Component Object myCompBean = context.getBean("myCompBean"); System.out.println(myCompBean); }}Copy the code

3.2 @ Bean

This note we use should also be quite many, we are very familiar with, but more introduction.

@Data public class MyAnnoBean { private String name = "myAnnoBean"; } @Configuration public class MyConfig { @Bean public MyAnnoBean myAnnoBean(){ return new MyAnnoBean(); } } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //anno Object myAnnoBean = context.getBean("myAnnoBean"); System.out.println(myAnnoBean); }}Copy the code

3.3 @ Named

Inject javax.inject dependency in THE POM

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
Copy the code
@Data @Named public class MyNamedBean { private String name="myNamedBean"; } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //@Named Object myNamedBean = context.getBean("myNamedBean"); System.out.println(myNamedBean); }}Copy the code

XML 3.4 way

I’m sure most of us are familiar with Spring’s XML configuration files (in fact, since the advent of Springboot, subsequent Spring users have really stopped using XML), but as Spring veterans, we certainly don’t forget our roots.

Create beans.xml in the Resources directory

<bean class="org.example.springbean.xml.MyXmlBean" id="myXmlBean"></bean>
Copy the code

Since we’re using Springboot to boot, XML also needs to be introduced via the @importResource annotation

@Configuration @ImportResource(locations={"beans.xml"}) public class XmlConfig { } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //xml Object myXmlBean= context.getBean("myXmlBean"); System.out.println(myXmlBean); }}Copy the code

3.5 the Properties way

Create beans.properties under the Resources directory

myPropertiesBean.(class)=org.example.springbean.props.MyPropertiesBean
Copy the code

So if you import an XML file with the @importResource annotation and you find that you can specify reader, the default implementation is XmlBeanDefinitionReader, Here you need to specify the reader = PropertiesBeanDefinitionReader. Class

@Configuration @ImportResource(locations={"beans.properties"},reader = PropertiesBeanDefinitionReader.class) public class PropsConfig { } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //properties Object myPropertiesBean = context.getBean("myPropertiesBean"); System.out.println(myPropertiesBean); }}Copy the code

3.6 the Groovy way

This may also be a way, in addition to the need to develop as XML reader = GroovyBeanDefinitionReader. Outside of class, also need extra to introduce a groovy – rely on XML

< the dependency > < groupId > org. Codehaus. Groovy < / groupId > < artifactId > groovy - XML < / artifactId > < version > 3.0.8 < / version > </dependency>Copy the code

Create a new beans.groovy in the Resources directory


import org.example.springbean.groovy.MyGroovyBean;

beans{
    myGroovyBean(MyGroovyBean){}
}
Copy the code
@Data public class MyGroovyBean { private String name="myGroovyBean"; } @Configuration @ImportResource(locations = {"beans.groovy"},reader = GroovyBeanDefinitionReader.class) public class GroovyConfig { } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //groovy Object myGroovyBean = context.getBean("myGroovyBean"); System.out.println(myGroovyBean); }}Copy the code

Properties, XML, groovy, etc. We can define our own file format for BeanDefinitionReader. But these three are already implemented by Spring and can be used directly. By the way, I’ve only used Xml in my career…

3.7 FactoryBean way

@Data public class MyFacBean { private String name = "myFacBean"; } @Component public class MyFacBeanFactory implements FactoryBean<MyFacBean> { @Override public MyFacBean getObject() throws Exception { return new MyFacBean(); } @Override public Class<? > getObjectType() { return MyFacBean.class; } @Override public boolean isSingleton() { return true; } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); MyFacBean = (myFacBean)context.getBean("myFacBean"); MyFacBean = context.getBean("myFacBeanFactory"); System.out.println(myFacBean); Object myFacBeanFactory = Context.getBean ("&myFacBeanFactory"); System.out.println(myFacBeanFactory); }}}Copy the code

3.8 @ Import

public class MyImportBean { private String name="myImportBean"; } @SpringBootApplication @Import(value = {MyImportBean.class}) public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //Object myImportBean = context.getBean("myImportBean"); Object myImportBean = context.getBean("org.example.springbean.ipt.MyImportBean"); System.out.println(myImportBean); }}}Copy the code

3.9 ImportSelector

@Data public class MyImportSelectorBean { private String name="myImportSelectorBean"; } public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{MyImportSelectorBean.class.getName()}; } } @SpringBootApplication @Import(value = {MyImportSelector.class}) public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //ImportSelector Object myImportSelectorBean = context.getBean("org.example.springbean.ipt.MyImportSelectorBean"); System.out.println(myImportSelectorBean); }}}Copy the code

3.10 ImportBeanDefinitionRegistrar

@Data public class MyImportBeanDefinitionRegistrarBean { private String name="importBeanDefinitionRegistrar"; } public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { RootBeanDefinition beanDefinition = new RootBeanDefinition(MyImportBeanDefinitionRegistrarBean.class); registry.registerBeanDefinition("myImportBeanDefinitionRegistrarBean", beanDefinition); } } @SpringBootApplication @Import(value = {MyImportBeanDefinitionRegistrar.class}) public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //ImportBeanDefinitionRegistrar Object myImportBeanDefinitionRegistrarBean = context.getBean("myImportBeanDefinitionRegistrarBean"); System.out.println(myImportBeanDefinitionRegistrarBean); }}}Copy the code

3.11 spring BeanFactoryPostProcessor

@Data public class MyBeanFactoryPostProcessorBean { private String name="myBeanFactoryPostProcessorBean"; } @Configuration public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { beanFactory.registerSingleton("myBeanFactoryPostProcessorBean",new MyBeanFactoryPostProcessorBean()); } } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //BeanFactoryPostProcessor Object myBeanFactoryPostProcessorBean = context.getBean("myBeanFactoryPostProcessorBean"); System.out.println(myBeanFactoryPostProcessorBean); }}}Copy the code

3.12 BeanDefinitionRegistryPostProcessor

@Data public class MyBeanDefinitionRegistryPostProcessorBean { private String name = "myBeanDefinitionRegistryPostProcessorBean"; } @Configuration public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { RootBeanDefinition rbd = new RootBeanDefinition(MyBeanDefinitionRegistryPostProcessorBean.class); registry.registerBeanDefinition("myBeanDefinitionRegistryPostProcessorBean", rbd); // If the construction parameters are particularly complex, BeanDefinitionBuilder // AbstractBeanDefinition rbd2 = BeanDefinitionBuilder.rootBeanDefinition(MyBeanDefinitionRegistryPostProcessorBean.class) // .addPropertyValue("name","myBeanDefinitionRegistryPostProcessorBean2") // .getBeanDefinition(); // registry.registerBeanDefinition("myBeanDefinitionRegistryPostProcessorBean2", rbd2); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { / / the same spring BeanFactoryPostProcessor, }} @springBootApplication public class BootStarter {public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //BeanDefinitionRegistryPostProcessor Object myBeanDefinitionRegistryPostProcessorBean = context.getBean("myBeanDefinitionRegistryPostProcessorBean"); System.out.println(myBeanDefinitionRegistryPostProcessorBean); }}}Copy the code

3.13 with the help of ApplicationContext

@Data public class CustomBean { private String name="customBean"; } @Component public class CustomContext { @Autowired private ApplicationContext applicationContext; @PostConstruct public void init(){ BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) this.applicationContext; RootBeanDefinition rbd = new RootBeanDefinition(CustomBean.class); beanDefinitionRegistry.registerBeanDefinition("customBean",rbd); } } @SpringBootApplication public class BootStarter { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootStarter.class); //custom Object customBean = context.getBean("customBean"); System.out.println(customBean); }}}Copy the code

All roads lead to Rome

There are about 13 ways to inject beans into a Spring container. There are some methods that we only need to know a little bit about, but if we want to learn Spring well, we need to know the important ones like ImportSelector, FactoryBean, BeanFactoryPostProcessor, You’ll encounter them a lot in future source code.

Five, the summary

Spring configures beans in two ways:

  1. Based on the way resource files are parsed, the most common one is XML configuration

Advantages: The Bean management pattern can be adjusted appropriately during late maintenance and, as long as certain naming conventions are followed, the programmer does not have to worry about dependencies between beans. Disadvantages: The larger the system, the larger the XML configuration files, which can be complex and error prone.

  1. JavaConfig based annotation configuration

Advantages: the configuration is convenient, we only need to set the code in the service layer to achieve, do not need to know how many beans the system needs, to the container for injection. Disadvantages: When you modify or delete a Bean, you can’t be sure how many other beans depend on it. (Solution: Strict development documentation is needed to continue to follow the interface rules as much as possible as you modify the implementation to avoid making other beans that depend on this unavailable.)

Having talked about how beans are configured, next time we’ll look at how they are discovered and assembled for use by the Spring container.

The core competitiveness of programmers is actually technology, so the technology or to continue to learn, pay attention to the “IT peak technology” public number, the public number content positioning: The author is the author of RocketMQ Technology Inside Message Middleware and the co-founder of RocketMQ Shanghai Community. He has worked for Pduo Duo, Deppon and other companies. As the head of architecture of listed express delivery company, I am mainly responsible for the construction of development framework, secondary development and operation and maintenance management of middleware related technologies, and construction of hybrid cloud and basic service platform.