spring annotation development: how components are registered in containers

Posted by poppy28 on Mon, 24 Jun 2019 19:39:28 +0200

1. Package Scan + Component Label Comments

The following comments are used, mainly for classes written by you

  • @Controller
  • @Service
  • @Repository
  • @Component
  • @ComponentScan

Reference resources spring Annotation Development: ComponentScan Component Scan

2. Use bean annotations

Main usage scenario: Import components from third-party packages with annotations:

  • @Bean
Reference resources: spring Annotation Development: Configuration&Bean

3. Use the @Import comment

  • Usage: @Import (component to be imported into container); this component is registered automatically in container
  • bean's id defaults to the class name
  • Example: @Import(value = {Person.class})

actual combat

1. Create a new maven project and add the following dependencies

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

2. Create a new entity Person

package com.yefengyu.annotation.bean;

public class Person
{
    private String name;

    private Integer age;

    public Person()
    {
    }

    public Person(String name, Integer age)
    {
        this.name = name;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public Integer getAge()
    {
        return age;
    }

    public void setAge(Integer age)
    {
        this.age = age;
    }

    @Override
    public String toString()
    {
        return "Person{" +
               "name='" + name + '\'' +
               ", age=" + age +
               '}';
    }
}

3. Create a new configuration class (focus)

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import(Person.class)
public class MainConfig
{
}

4. Test Code

public static void main(String[] args)
{
    ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
    String[] names = ctx.getBeanDefinitionNames();
    for (String name : names)
    {
        System.out.println(name);
    }
    Person person1= (Person)ctx.getBean(Person.class);
    //bean Of id The default is the class name
     Person person2= (Person)ctx.getBean("com.yefengyu.annotation.bean.Person");
}

4. Use ImportSelector

ImportSelector is used with Import: Write a class to implement the ImportSelector interface MyImportSelector, and then add MyImportSelector to Import, then the MyImportSelector custom logic returns the components that need to be imported and is added to the container.

Using the code in the third section above, we re-added a class that has nothing, and now we're trying to register it in a container using ImportSelector.

package com.yefengyu.annotation.bean;

public class Car
{
}

1. Write MyImportSelector to implement the ImportSelector interface, override the selectImports method, and return an array in which each string is the full class name of the component to be imported into the container.

package com.yefengyu.annotation;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

//Custom logic returns components that need to be imported
public class MyImportSelector implements ImportSelector
{
    //The return value is the full class name of the component to be imported into the container
     @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata)
    {
        return new String[]{"com.yefengyu.annotation.bean.Car"};
    }
}

2. Modify the MainConfig configuration class and use the Import annotation to add the MyImportSelector class. Note the red section below.

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class})
public class MainConfig
{
}

3. Test, also use the test code above, you can see that the printed results are:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car

4. There is a lot of information about the parameter AnnotationMetadata in the public String[] selectImports (AnnotationMetadata annotation Metadata) method to help filter the components to be registered.

5. Use ImportBeanDefinitionRegistrar

As with ImportSelector, define a class that implements the ImportBeanDefinitionRegistrar interface, override its methods, and manually register components.

1. Set a class as the component to be registered

package com.yefengyu.annotation.bean;

public class Alarm
{
}

2. Implement the ImportBeanDefinitionRegistrar interface to manually register components

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Alarm;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;


public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
{
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
                                        BeanDefinitionRegistry beanDefinitionRegistry)
    {
        beanDefinitionRegistry.registerBeanDefinition("alarm",new RootBeanDefinition(Alarm.class));
    }
}

beanDefinitionRegistry.registerBeanDefinition("alarm",new RootBeanDefinition(Alarm.class));

The first parameter is the component name.

The second parameter is the definition of the type of component to be registered.

AnnotationMetadata is similar to the previous section.BeanDefinitionRegistry has many features:

3. Modify the MainConfig configuration class and use the Import annotation to add the MyImportBeanDefinitionRegistrar class. Note the red section below.

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.MyImportBeanDefinitionRegistrar;
import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig
{
}

4. Test, also use the test code above, you can see that the printed results are:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car
alarm

6. Use FactoryBean

1. First create a component to be added to the container

package com.yefengyu.annotation.bean;

public class Event
{
}

2. Create a FactoryBean defined by Spring

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Event;
import org.springframework.beans.factory.FactoryBean;


//Create a Spring Defined FactoryBean
public class EventFactoryBean implements FactoryBean<Event>
{
    //Return a Event Object, which is added to the container
    @Override
    public Event getObject()
        throws Exception
    {
        return new Event();
    }

    @Override
    public Class<?> getObjectType()
    {
        return Event.class;
    }

    //Is it a singleton?
    //true: this bean Is a single instance, keeping a copy in a container
    //false: Multiple instances, each acquisition creates a new bean;
    @Override
    public boolean isSingleton()
    {
        return true;
    }
}

3. Modify the configuration class and note the code below in the bean comment

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.EventFactoryBean;
import com.yefengyu.annotation.MyImportBeanDefinitionRegistrar;
import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig
{
    @Bean
    public EventFactoryBean eventFactoryBean()
    {
        return new EventFactoryBean();
    }
}

4. Modify the test code as follows:

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Person;
import com.yefengyu.annotation.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class Main
{
    public static void main(String[] args)
    {
        ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
        String[] names = ctx.getBeanDefinitionNames();
        for (String name : names)
        {
            System.out.println(name);
        }
        //test EventFactoryBean
        Object eventFactoryBean = ctx.getBean("eventFactoryBean");
        System.out.println("bean The type of is:" + eventFactoryBean.getClass());

        Object factoryBean = ctx.getBean("&eventFactoryBean");
        System.out.println("bean The type of is:" + factoryBean.getClass());
    }
}

5. The results are as follows:

mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car
eventFactoryBean
alarm
bean The type of is:class com.yefengyu.annotation.bean.Event
bean The type of is:class com.yefengyu.annotation.EventFactoryBean

Summary:

  • The default is the object created by the factory bean calling getObject

    ctx.getBean("eventFactoryBean");

  • To get the factory Bean itself, we need to precede the id with an &

    ctx.getBean("&eventFactoryBean");

Topics: PHP Spring Maven