Have you always been using @Service, @Component, @Contoller or @ Bean to add your Spring beans? Have you seen some of the others’ code that looks fancy in injecting the beans but don’t know how it achieves the same purpose? Let’s take a look at some common ways to inject Spring beans into the container. This might be the most common one. For the same example, we can declare the Person object as a Component. We will then use @ComponentScan “basePackages” to declare the paths for the components. There are various flexible ways to use this annotation. Direct import bean. Once we are done constructing the Person class, we can then import the class into the Spring container. We can also define a MyImportSelector to realize ImportSelector interface and override selectImports method, in which we will specify beans we need. Now we only need to import the MyImportSelector class. For this method, we also need to realize an interface ImportBeanDefinitionRegistrar. The difference between this method and the previous one is an additional declaration of “beanDefinition” — the metadata of the bean. FactoryBean is a bean itself, which, by the way, not to be confused with BeanFactory that manages beans. Here we use method 1 — @Configuration + @Bean to add PersonFactoryBean into the Spring container. However, notice that I didn’t inject Person bean directly in @Bean. Instead, PersonFactoryBean is injected. Spring container then gets the Person bean from the factory bean. When Spring container executes postProcessBeanDefinitionRegistry method in BeanDefinitionRegistryPostProcesso, it will process the beanDefinition separately, which we can use to adjust the beanDefinition.1. @Configuration + @Bean
@ Configuration declares a configuration class and we can use @ Bean to add the bean into the container.@Configuration
public class MyConfiguration {
@Bean
public Person person() {
Person person = new Person();
person.setName("spring");
return person;
}
}
2. @Component + @ComponentScan
@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);
}
}
3. @Import
3.1 Direct import bean
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 + '\'' +
'}';
}
}
@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);
}
}
3.2 @Import + ImportSelector
@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"};
}
}
3.3 @Import + ImportBeanDefinitionRegistrar
@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) {
// construct beanDefinition
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
// register the bean into the container
registry.registerBeanDefinition("person", beanDefinition);
}
}
4 @FactoryBean
@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;
}
}
5 BeanDefinitionRegistryPostProcessor
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 {
}
}