Contents
Several ways to hand over beans to Spring container management
Spring core
SpringThe core is IOC and AOP .
The so-called IoC, for springthe framework, is responsible springfor controlling the life cycle of objects and the relationship between objects.
As for a more detailed explanation, or to deeply understand Springthese two cores, it is not the purpose of this article, so I will not go into detail yet.
In our Springproject, we need to hand Beanit over to Springthe container, that is, IOC management, so that you can use annotations for dependency injection.
Package scanning + component annotation
For the case where the class is written by ourselves
This method is most commonly used in our daily development to add classes with , , , annotations springunder the scan path to the container.@Component@Controller@Service@Repositoryspring IOC
If you have used MybatisPlus, this is the same as its package scanning injection.

Then our ComponentScanannotation has three configurations.
Configuration item one
basePackagesPath used to define scanned packages.
@ComponentScan(basePackages = "com.timemail.bootmp")
For example, this is to scan com.timemail.bootmpthe entire package for classes with the above specified annotations and put them in IOC.
I found a complete example in another article:
@Component
public class Person {
private String name;
public String getName () {
return name;
}
public void setName (String name) {
this .name = name;
}
@Override
public String toString () {
return "Person{" +
"name='" + name + '\'' +
'}' ;
}
}
@ComponentScan(basePackages = "com.springboot.initbean.*")
public class Demo1 {
public static void main (String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (Demo1.class);
Person bean = applicationContext.getBean(Person. class);
System.out.println(bean);
}
}
//Result
Person{name= 'null' }
This shows that Personthe class in the above code has been managed by the IOC container.
Configuration item two
includeFiltersinclude rules
Filter annotation uses FilterType.CUSTOM to customize scanning rules. You need to implement the TypeFilter interface to implement the match method. The parameter MetadataReader is the current class information (annotations, class path, class source information…) MetadataReaderFactory MetadataReader factory class.
Configuration item three
excludeFiltersRemove rule
Same inclusion rules.
I haven’t used these last two configuration items much, and I’m not very familiar with them, so please check the relevant information for detailed use.
@Configuration+@Bean
@Configuration+ @Beanis also a commonly used way for us to put it into containers.
@ConfigurationUsed to declare configuration classes
@Beanused to declare aBean
@Configuration
public class Demo {
@Bean
public Person person () {
Person person = new Person ();
person.setAge( 10 );
return person;
}
}

like this.
Then we know that SSMinside, usually we will configure it in xml bean.
@Configuration
public class ConfigBean {
}
Then our @Configurationannotation is equivalent to a Beanconfiguration xml.
<?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-4.3.xsd" >
</beans>
Properties in Bean annotations
Our @Beanannotations also have many properties that can be configured.
We can view its source code:
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) //@1
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};
@AliasFor("value")
String[] name() default {};
@Deprecated
Autowire autowire () default Autowire.NO;
boolean autowireCandidate () default true ;
String initMethod () default "" ;
String destroyMethod () default AbstractBeanDefinition.INFER_METHOD;
}
- value and name are the same. When setting, you can only choose one of these two parameters. The reason is caused by @AliasFor
- value: string array, the first value is used as the name of the bean, and other values are used as aliases of the bean
- autowire: This parameter is marked @Deprecated, which means it has expired and is not recommended for use.
- autowireCandidate: Whether to serve as a candidate bean when injecting other objects.
- initMethod: bean initialization method. This is related to the life cycle and will be explained in detail later.
- destroyMethod: The method of bean destruction, which is also related to the life cycle and will be explained in detail later.
Expand
For @Configurationa modified class, springthe container will cglibcreate a proxy for this class. The proxy will intercept all modified @Beanmethods beanand ensure that these methods are only called once by default (single case) to ensure that these beanare the same bean, that is, singleton Example.
@Import annotation import
Let’s look at the source code first:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* Used to import a class file
* { @link Configuration @Configuration }, { @link ImportSelector},
* { @link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
@ImportCan only be used for class annotations.
Here I will directly transfer the content of the public account: Xiaoha learns Java.
His explanation is very detailed.
The first two methods may be used more often and must be known in daily development. The @Import annotation may not be used particularly much, but it is also very important. It is often used when extending Spring. It is often used. Use it with custom annotations, and then import a configuration file into the container.
Regarding the @Import annotation, I will introduce a little more. It has four ways to use it. This is the source code of the @Import annotation, which means it can only be placed on a class.
@Import directly imports classes
public class Person {
private String name;
public String getName () {
return name;
}
public void setName (String name) {
this .name = name;
}
@Override
public String toString () {
return "Person{" +
"name='" + name + '\'' +
'}' ;
}
}
/**
* Directly use @Import to import the person class, then try to get it from the applicationContext, and get it successfully
**/
@Import(Person.class)
public class Demo1 {
public static void main (String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
The above code directly @Importimports a class, and then it is automatically placed in IOCthe container.
Note: Our
Personclass does not need any annotations, just import it directly.
@Import + ImportSelector
In fact @Import, it is very clear in the source code of the annotation. If you are interested, you can take a look. We implement an ImportSelectorinterface, then implement the methods in it and import it.
@Import(MyImportSelector.class)
public class Demo1 {
public static void main (String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String []{ "com.springboot.pojo.Person" };
}
}
I customized a MyImportSelectorcustom ImportSelectorinterface, overridden selectImportsthe method, and then wrote the fully qualified name of the class we want to import in it. It is also very simple to implement.
@Import + ImportBeanDefinitionRegistrar
This method also requires us to implement ImportBeanDefinitionRegistrarthe methods in the interface. The specific code is as follows:
@Import(MyImportBeanDefinitionRegistrar.class)
public class Demo1 {
public static void main (String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions (AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// Build a beanDefinition. I will introduce beanDefinition later, which can be simply understood as the definition of bean.
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
// Register the beanDefinition into the Ioc container.
registry.registerBeanDefinition( "person" , beanDefinition);
}
}
The above implementation is actually Importsimilar to the second method. Both need to implement the interface and then import it. I came into contact with a new concept, BeanDefinitionwhich can be simply understood as beanthe definition ( beanmetadata) of , which also needs to be managed in an IOC container. The metadata beanis created , applicationContextand then beanthe metadata is created Bean.
@Import + DeferredImportSelector
This method also requires us to implement the interface. In fact , it is @Importsimilar to the second method. DeferredImportSelectorIt is ImportSelectora sub-interface of , so the implementation method is the same as the second method. It’s just Springthat the processing method is different, it Spring Bootis related to the delayed import of the automatic import configuration file, which is very important. How to use it:
@Import(MyDeferredImportSelector.class)
public class Demo1 {
public static void main (String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyDeferredImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// Also put Person's fully qualified name directly
return new String []{Person.class.getName()};
}
}
Regarding @Importthe use of annotations, there are probably the above three methods. Of course, it can also be used with @Configurationannotations to import a configuration class.
FactoryBean interface
Speaking of which FactoryBean, many of our entry-level developers can easily confuse him with BeanFactory.
BeanFactoryIt is the container root interface of all Spring Beans. It defines a set of specifications for Spring containers and provides a complete set of specifications for IOC containers, such as the commonly used getBean method.That is what we often call
Beana factory.
And ours FactoryBean, it’s actually one Bean, Factoryit’s his name, as the name suggests.
@Configuration
public class Demo1 {
@Bean
public PersonFactoryBean personFactoryBean () {
return new PersonFactoryBean ();
}
public static void main (String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class PersonFactoryBean implements FactoryBean <Person> {
@Override
public Person getObject () throws Exception {
return new Person ();
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
}
Here, we can first look at FactoryBeanthe method in:

It is an interface class.
Then we need to have a class to inherit this interface and override the method.

BeanHere, we put the classes that need to be registered FactoryBeaninto the generics.
getObjectMethod is used to directly return the created object.
getObjectTypeReturn the class directly class.
Then in fact, you still need to use @Beanannotations to return the class object that inherits the interface.

Then Configurationannotate and change this class springbootto the configuration class, which is equivalent to the file springmvcin xml.
We can use AnnotationConfigApplicationContextthe getBeanmethod to see if it is IOCmanaged.

After running, you can see that the object address is output.
It means success.
Using BeanDefinitionRegistryPostProcessor
When writing this article, I also checked the information of many big names on the Internet.
There is a method that I’m not familiar with.
then……
Start copying the original text….
In fact, this method is also used . It is a method that
BeanDefinitionRegistrywill be executed when the Spring container is started . It probably means that after the beanDefinition is loaded, the beanDefinition will be post-processed. You can adjust the beanDefinition in the IOC container here to interfere with the later. Initialize the bean.
BeanDefinitionRegistryPostProcessor
postProcessBeanDefinitionRegistry ()
public class Demo1 {
public static void main (String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
MyBeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = new MyBeanDefinitionRegistryPostProcessor ();
applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);
applicationContext.refresh();
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry (BeanDefinitionRegistry registry) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
registry.registerBeanDefinition( "person" , beanDefinition);
}
@Override
public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
In the above code, we manually registered person in beanDefinitionRegistry BeanDefinition, and finally successfully added person to applicationContext.
