Spring annotation driven development learning

Posted by EOS on Fri, 07 Feb 2020 14:28:21 +0100

Learning route

1. container

spring believes that all components should be placed in the container and used through the automatic assembly of the container
When developing based on annotations, the configuration class is the same as the previous configuration file
@Configuration indicates that this is a configuration class

@Target({ElementType.TYPE})//Can only be marked on a class
@Retention(RetentionPolicy.RUNTIME)//Storage
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

1.1 bean annotation

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})//Mark on methods and annotation classes
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
    @AliasFor("name")
    String[] value() default {};

    @AliasFor("value")//Tag the id used to represent the bean
    String[] name() default {};

    /** @deprecated */
    @Deprecated
    Autowire autowire() default Autowire.NO;

    boolean autowireCandidate() default true;

    String initMethod() default "";

    String destroyMethod() default "(inferred)";
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
/**
 * This is a configuration class
 */
public class MainConfig {
    @Bean
    /**
     * Register a bean for the container
     * Class with return value of bean
     * id The default is to use the method name as the id
     */
    public person person(){
        return new person();
    }
}


import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class mainTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        person bean = applicationContext.getBean(person.class);
        System.out.println(bean);
    }
}

@componentScan package scan annotation

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})//Mark on class
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")//The package specified to scan can be an array, that is, multiple packages specified to scan
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

							//ComponentScan.Filter is a comment written below
    ComponentScan.Filter[] includeFilters() default {};//What annotations are included in the scan

    ComponentScan.Filter[] excludeFilters() default {};//Exclude comments when scanning

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;//According to the annotation rule, this is an enumeration class

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}


public enum FilterType {
    ANNOTATION,//According to annotation class
    ASSIGNABLE_TYPE,//According to the specified class, such as{BookService.class}Write like this
    ASPECTJ,//
    REGEX,//By regular expression
    CUSTOM;//Custom rule, write a TypeFilter Implementation class

    private FilterType() {
    }
}

@ComponentScan(value = {},includeFilters = {
        @ComponentScan.Filter(Type= FilterType.ANNOTATION,classes = {Service.class, Controller.class})
})
/**
 * Tag Package scan
 * value The specified package represented in
 * includeFilters Scan policy, Type= FilterType.ANNOTATION include as annotation
 * Used to scan the spring annotations under the specified package, such as @ service @ component @ controller @ repeatability, etc
 * Mark on class
 */

Scope annotation set component scope

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
    @AliasFor("scopeName")
    String value() default "";

    @AliasFor("value")
    String scopeName() default "";

    ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
@Scope(value = "Prototype")//"" singleton prototype
public person person(){
    return new person();
}

@Lazy set bean lazy loading

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
    boolean value() default true;
}

Marks are used on methods or classes to indicate that the marked components enable lazy loading
That is, instead of creating beans when ioc containers are created, beans are created when they are called

@conditional register bean by condition

The value passed in when the conditional annotation is used is a condition object
We need to write our own concrete objects to implement the condition interface

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
public class MyCondition implements Condition {
    @Override
    /**
     * ConditionContext:Determine the context in which the condition can be used
     * AnnotatedTypeMetadata: Annotation information with condition annotation currently marked
     */
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //bean factory
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //Get class loader
        ClassLoader classLoader = conditionContext.getClassLoader();
        //Access to environmental information
        Environment environment = conditionContext.getEnvironment();
        //Get bean definition registrar
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        //
        String property = environment.getProperty("os.name");

        if (property.contains("Windows")){

            return  true;
        }

        return false;
    }
}


//Specific use
@Bean("person2")
@Conditional({MyCondition.class})
public person person2(){
    return new person();
}

@Import quick import components to container

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    Class<?>[] value();
}~
1. The first method of use
@Import(person.class)
Mark directly on class
 The id of the registered class is the full class name of the class
@Import(person.class)
public class MainConfig {~
2. Register through ImportSelector
 You need to create an object that implements the ImportSelector interface and pass it into the value of import
public class MyImportSelector implements ImportSelector {
    @Override
    //The return value is the full class name of the class to be imported into the container
    //annotationMetadata can obtain the annotation information of all annotations marked by the current class
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //The full class name of the class to be implemented when the string array is placed
        return new String[]{"person"};
    }
}~

@Import(MyImportSelector.class)
public class MainConfig {~
3. Register through the importbeandefinitionregister object

Create an importbeandefinitionregister~
The implementation class of the interface is passed into the value attribute value of the import

public class BeanDefination implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param importingClassMetadata Annotation information for tagged classes
     * @param registry  Register bean definition
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
        registry.registerBeanDefinition("person",new RootBeanDefinition(person.class));
    }
}~

@Import(BeanDefination.class)
public class MainConfig {~
~

@FactoryBean registration component

Create an implementation class that implements the factorybean interface
It is stored in the container through @ bean. The name of the method is the id of the class

public class personTest implements FactoryBean {
    @Override
    //Return a single implementation class
    public Object getObject() throws Exception {
        return new person();
    }

    @Override
    //Class object array of implementation class
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    //Judge whether it is a single case
    public boolean isSingleton() {
        return false;
    }
}~


//When used
@Bean
public FactoryBean factoryBean(){
    return new personTest();
}~

Set bean life cycle

External resource file

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
    String name() default "";

    String[] value();//The path of the configuration file can be imported more than one at a time starting from class path

    boolean ignoreResourceNotFound() default false;

    String encoding() default "";

    Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
~

When fetching the property value of the configuration file, the value (${ }

automatic assembly

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;//This property can be used to set whether the component must be injected. If it is true, then
}~

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
    String value() default "";
}~

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {
}~

/**

  • Automatic assembly:
  •  spring uses dependency injection to automatically store corresponding components
    
  • Notes:
  •  @Autowired: Auto injection (priority to find and assign values according to types, if there are multiple components of corresponding types at the same time
    
  •              Just use the property name as the component id to find the component in the container and assign a value)
    
  •  @Qualifier: load according to the specified id. if there is no component with the specified id in the container, an exception will be reported
    
  •  @Primary: this cannot be used with Qualifier. Its function is to specify a preference for a component, so that the component has the highest priority
    

*/~

Aware interface

Profile register bean s according to environment


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
String[] value(); / / environment ID
}~

Published 39 original articles, won praise 2, visited 586
Private letter follow

Topics: Java Spring IntelliJ IDEA Windows