Analysis of Common Annotations in Spring

Posted by tdeez173 on Wed, 29 May 2019 20:35:31 +0200

1. Common Notes

1.1 @Configuration

@Configuration
public class MainConfig {
}

@ The Configuration annotation indicates that this class is a configuration class that should contain details on how to create bean s in the context of Spring applications.

1.2 @ComponentScan

@Configuration
@ComponentScan("per.ym")
public class MainConfig {
}

@ ComponentScan annotations are used to enable component scanning, which works the same way as configuring <context: component-scan> in xml. The above configuration scans all classes under per.ym package, and if the value value value is not configured, it scans components with the package in which the configuration class resides as the base package. If you want to scan multiple packages at the same time, you can configure it as follows:

@Configuration
@ComponentScan("per.ym, per.mm")
public class MainConfig {
}

In the example above, the underlying package is set in String type. I think it is possible, but this method is not type-safe. If you refactor the code, the specified base package may have errors. In addition to setting packages as simple String types, @ComponentScan provides another way to specify them as classes or interfaces contained in packages:

@Configuration
@ComponentScan(basePackageClasses = {MyService.class,  MyDao.class})
public class MainConfig {
}

You might consider creating a marker interface in the package for scanning. By marking the interface, you can still preserve it.
Keep refactoring-friendly interface references, but avoid referencing any actual application code

1.3 @Controller, @Service, @ Repository, @Component

Needless to say, these are the most common ones. Their lock-modified classes will be added to spring management when they are scanned by spring containers.

@ Controller's Bean for the Representation Layer

@ Service corresponds to Business Layer Bean

@ Repository Corresponds to Data Access Layer Bean

@ Component, when you can't explicitly select the 3 above, use this

All bean s in the Spring application context will be given an ID. If not explicitly specified, Spring will specify an ID based on the class name, that is, the first letter of the class name will be lowercase. You can also specify an ID as shown here:

@Component("ymm")
public class Person() {
}

Spring supports @Named (provided in the Java dependency injection specification) as an alternative to the @Component annotation. There are some subtle differences between the two, but in most scenarios they can be replaced by each other.

1.4 @Bean

@ The Bean annotation tells Spring that this method will return an object that will be registered as a Spring application context.
Bean. The body of the method contains the logic that ultimately generates the bean instance.

@Configuration
public class MainConifg {
    @Bean
    public BookDao bookDao(){
        return new BookDao();
    }
}

@ The Bean annotation tells Spring that this method will return an object that will be registered as a Spring application context.
Bean. The body of the method contains the logic that ultimately generates the bean instance.

By default, the ID of the bean is the same as the method name with the @Bean annotation. In the example above, the bean's name will be bookDao. If you want to set it to a different name, you can rename the method, or you can specify a different name through the name attribute:

@Configuration
public class MainConifg {
    @Bean(" ymBookDao")
    public BookDao bookDao(){
        return new BookDao();
    }
}

You can also set initialization and destruction methods like this:

@Configuration
public class MainConifg {
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public BookDao bookDao(){
        return new BookDao();
    }
}

This is like configuring init-method="init" destroy-method="destory" in xml

1.5 @Autowired

Spring auto-assembly can be realized by @Autowire annotation. Auto-assembly is a way to make Spring automatically satisfy bean dependencies. In the process of satisfying dependencies, other beans matching the requirements of a bean will be found in the context of Spring application.

@Service
public class BookService {

    @Autowired(required=false)
    private BookDao bookDao;

}

You can tag @Autowire on attributes, constructors, setter methods. In fact, there is nothing special about the Setter method, and the @Autowire annotation can even be used on any method of a class.

In addition to @Autowired, spring also supports @Resource(JSR250) and @Inject(JSR330) in the Java specification. The differences between them are as follows:

@Autowired:

a. By default, it is preferable to find the corresponding component in the container according to the type: application Context. getBean (BookDao. class). If and only one bean matches the dependency requirement, the bean will be assembled. If multiple components of the same type are found, the name of the attribute will be used as the id of the component to find the application Context. getBean ("bookDao") in the container.

b, @Qualifier("bookDao"): Use @Qualifier to specify the id of the component that needs to be assembled explicitly, instead of using the attribute name;

c. Autowired(required=false) can be used by default.

d, @Primary: When Spring is automatically assembled, the preferred bean is used by default; you can also use @Qualifier to specify the name of the bean that needs to be assembled;

@Resource:

a, as @Autowired, it implements automatic assembly; by default, it is assembled according to the name of the component;

b, the @Primary function is not supported;

c, does not support the required=false function;

@Inject:

a. The automatic assembly function is implemented as @Autowire.

b, does not support the required=false function;

A possible example:

@Configuration
@ComponentScan("per.ym.service")
public class MainConifgOfAutowired {

    @Primary
    @Bean("bookDao1")
    public BookDao bookDao1(){
        BookDao bookDao = new BookDao();
        bookDao.setLable("1");
        return bookDao;
    }

   @Bean("bookDao2")
   public BookDao bookDao2(){
     BookDao bookDao = new BookDao();
     bookDao.setLable("2");
     return bookDao;
   }
}   

@Service
public class BookService {

    @Qualifier("bookDao1")
    @Autowired(required=false)
    private BookDao bookDao;

    //@Resource(name="bookDao2")
    //private BookDao bookDao;

    //@Qualifier("bookDao2")
    //@Inject
    //private BookDao bookDao;
}

public class BookDao {

    private String lable = "0";

    public String getLable() {
        return lable;
    }

    public void setLable(String lable) {
        this.lable = lable;
    }
}

1.6 @Import

Import components into containers quickly by importing them. Three types of values can be configured on them: ordinary beans, Import Selector, ImportBean Definition Registrar. In particular, you can import a bean modified by the @Configuration annotation, similar to importing other configuration files using <import resource="classpath*:/spring/other.xml"/> in a spring configuration file.

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

MainConfig2 can be another configuration class or a normal bean:

@Configuration
public class MainConfig2 {

    @Bean
    public Person person(){
        return new Person();
    }
}

ImportSelector, whose selectImports method returns an array containing the full name of the bean to be imported into the container

public class MyImportSelector implements ImportSelector {

    //The return value is the full class name of the component imported into the container
    //AnnotationMetadata: All annotation information for classes currently annotated with @Import annotation
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //Method does not return null value, otherwise there will be NPE
        return new String[]{"per.ym.bean.Car","per.ym.bean.Dog"};
    }

}

ImportBean Definition Registrar calls BeanDefinition Registry. RegiserBeanDefinition to manually register the bean s you want to add to the container

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata: Annotation information for the current class
     * BeanDefinitionRegistry:BeanDefinition Registration class;
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //Specify Bean Definition Information
        RootBeanDefinition beanDefinition = new RootBeanDefinition(Red.class);
        //Register a bean, specify the bean name
        registry.registerBeanDefinition("red", beanDefinition);
    }

}

1.7 @Conditional

On a class, all bean registrations configured in that class take effect when conditions are met

On the method side, the current bean is registered with the container only when the condition is satisfied.

@Conditional({WindowsCondition.class})
@Configuration
public class MainConfig {

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person(){
        return new Person("linus");
    }
}

/**
* ConditionContext: Judging the context (environment) in which conditions can be used
* AnnotatedTypeMetadata: annotation
*/
//Judging whether a windows system is available or not
public class WindowsCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //1. beanfactory for ioc
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();

        //2. Getting Class Loader
        ClassLoader classLoader = context.getClassLoader();

        //3. Get the registered class defined by the bean
        BeanDefinitionRegistry registry = context.getRegistry();

        //4. Access to current environmental information
        Environment environment = context.getEnvironment();

        String property = environment.getProperty("os.name");
        if(property.contains("Windows")){
            return true;
        }

        return false;
    }

}

1.8 @Profile

Activate and switch the functions of a series of components dynamically according to the current environment; specify the circumstances under which components can be registered in containers, not specified, and can be registered in any environment.

Beans with environment labels can only be registered in containers when the environment is activated

Written on the configuration class, all the configurations in the entire configuration class will take effect only if they are in the specified environment.

@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{

    @Value("${db.user}")
    private String user;

    private StringValueResolver valueResolver;

    private String  driverClass;

    @Profile("test")
    @Bean("testDataSource")
    public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }

    @Profile("dev")
    @Bean("devDataSource")
    public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }

    @Profile("prod")
    @Bean("prodDataSource")
    public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/prod");

        dataSource.setDriverClass(driverClass);
        return dataSource;
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.valueResolver = resolver;
        driverClass = valueResolver.resolveStringValue("${db.driverClass}");
    }

}

db.properties:

db.user=root
db.password=123456
db.driverClass=com.mysql.jdbc.Driver

Set environment parameters on the start command line:

-Dspring.profiles.active=test

Code mode settings:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
applicationContext.getEnvironment().setActiveProfiles("dev");

Topics: Java Spring JDBC MySQL xml