Spring annotation - component registration

The emergence of Spring Boot greatly simplifies our development, so that we don't need to write complicated configuration files. It just makes use of the convenience of annotation, and Spring Boot relies on Spring, so it is necessary to study Spring annotation in depth.

Component registration related notes

@Configuration

Write on the class, declare that this class is a configuration class, instead of an xml file

@Bean

Effect:

Register a Bean in the IOC container, which is generally added to the method. The component type is the return value of the method, and the id is the method name by default

Common properties:

  • value / name: Specifies the name of the component. If not specified, the default is the method name
  • initMethod: specify initialization method
  • destroyMethod: specify the destruction method

@ComponentScan

Effect:

According to the custom rules, all components in the IOC container are scanned automatically. After jdk1.8, multiple @ ComponentScan can be defined on a class.

There is also a @ ComponentScan annotation. You can also define multiple @ ComponentScan in it

Common properties:

  • value / basePackages: Specifies the package name to scan
  • @Filter: rules used to specify filtering
    • Type: filter type
      • FilterType.ANNOTATION: by annotation
      • Filtertype.assignable'type: according to the given type
      • FilterType.ASPECTJ: use an ASPECTJ expression
      • FilterType.REGEX: using regular expressions
      • FilterType.CUSTOM: custom type
    • value / classes: filter values
    • pattern: filter rules. Different rules are configured according to different filter types
  • useDefaultFilters: whether to use the default filter rule, which is true by default
  • Include filters: specifies what components are included in the scan. You need to configure the useDefaultFilters property to false
  • excludeFilters: specifies which components are excluded according to what rules when scanning
  • lazyInit: lazy load

How to use FilterType.CUSTOM to customize filter rules?

public class MyTypeFilter implements TypeFilter {

    /**
     * Match method to determine whether the filter matches the class described by the given metadata
     * @param metadataReader Read the information of the currently scanning class
     * @param metadataReaderFactory You can get information about any other class
     * @return true:Match, false: mismatch
     * @throws IOException
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //Get annotation information of current class
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //Get information about the class currently being scanned
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //Get the current class resource (the road force of the class)
        Resource resource = metadataReader.getResource();

        //Custom matching rules
        String className = classMetadata.getClassName();
        if(className.contains("Controller")){
            return true;
        }
        return false;
    }
}

@Scope

Effect:

Adjust scope

Common parameters:

  • value / scopeName
    • singleton: for a single instance, when the ioc container starts, it will call methods to create bean objects. In the future, each retrieval is directly from the ioc container (map.get()).
    • prototype: multi instance. When the ioc container is started, it will not be called. It will be created when the bean object is obtained from the ioc container.
    • Request: create an instance at the same request.
    • Session: create an instance of the same session scope.
    • Global session: create an instance in the global session range, which is generally used for clustering.

@Lazy

Lazy loading is generally used in singleton mode. The bean will not be created when the container is started, but only when it is called for the first time

@Conditional

Effect:

Judge according to certain conditions. Only when the conditions are met can the bean be registered. It can be placed on a method or class. This annotation is widely used in the Spring Boot bottom layer

Common parameters:

  • value: pass in a class that inherits the Condition interface (multiple can be passed in), in which you define the conditions you need

@Import

Effect:

Import the specified components to the ioc container

Common parameters:

  • value: pass in the specified class. The id is the full class name by default. Custom classes, ImportSelector, and importbeandefinitionregister can be passed in

Usage:

Add the following form of annotation to the configuration class

@Import({Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})

ImportSelector

Pass in the class that implements the ImportSelector interface and return a full class name array. The advantage is that you can customize the components you need to import

public class MyImportSelector implements ImportSelector {

    /**
     * Custom imported components
     * @param importingClassMetadata All annotation information of the class currently annotated with @ Import annotation
     * @return Return full class name
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.spring.color.Blue", "com.spring.color.Yellow"};
    }
}

Break debug and you can see the parameter information, which is indeed the annotation information on the current @ Import class

ImportBeanDefinitionRegistrar

Manually register the bean into the container and call the registerBeanDefinition() method

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param importingClassMetadata All annotation information of the class currently annotated with @ Import annotation
     * @param registry Information about registered components in the container
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        int count = registry.getBeanDefinitionCount();
        if(count > 10){
            BeanDefinition beanDefinition = new RootBeanDefinition(Ten.class);
            registry.registerBeanDefinition("ten", beanDefinition);
        }
    }
}

Registering components with FactoryBean

Customize a class to implement the FactoryBean interface

public class FoodFactoryBean implements FactoryBean<food> {

    /**
     * Get instance object
     * @return
     * @throws Exception
     */
    @Override
    public Food getObject() throws Exception {
        return new Food();
    }

    /**
     * Get instance type
     * @return
     */
    @Override
    public Class<!--?--> getObjectType() {
        return Food.class;
    }

    /**
     * Single case, true: single case, false: multiple cases
     * @return
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

Register to container with @ Bean

@Bean
public FoodFactoryBean foodFactoryBean(){
    return new FoodFactoryBean();
}

Test it.

@Test
public void test2(){
    Object bean = applicationContext.getBean("foodFactoryBean");
    System.out.println("foodFactoryBean Type:" + bean.getClass());
}

The running result is as follows. It is found that the type is not FoodFactoryBean. Is the component type registered with @ Bean not the return value of the method? In fact, when FoodFactoryBean registers, it calls the getObject() method, so it registers the Food class

foodFactoryBean Type: class com.spring.bean.Food

So what if you want to get the FoodFactoryBean class?

Take a look at the source code of BeanFactory, which defines a member variable factory bean prefix

This variable is used to dereference the FactoryBean instance and distinguish it from the bean created by FactoryBean.

>For example, if the bean named test is a FactoryBean, getting & test returns the factory, not the instance returned by the factory.

So in getBean, add & before id

@Test
public void test2(){
    Object bean = applicationContext.getBean("&amp;foodFactoryBean");
    System.out.println("foodFactoryBean Type:" + bean.getClass());
}

summary

How to register components:

  1. Package scan (@ ComponentScan) + Component annotation (@ Component / @Controller / @Service / @Repository)
  2. @Bean [import components from third-party package]
  3. @Import [quickly import components to the container]
    • Common class: register directly. The id is the full class name by default
    • ImportSelector: returns the full class name array of components to be registered
    • Importbeandefinitionregister: manually register components into a container
  4. Use FactoryBean provided by spring
    • The default is to get the object returned by the FactoryBean calling the getObject method
    • You can add a & sign before the id when you get the Bean to get the FactoryBean itself < / food >

Tags: Programming Spring Session xml

Posted on Tue, 17 Mar 2020 09:52:20 -0400 by PHP-Editors.com