Application of Spring core annotation

Overall introduction to Spring framework functions

Spring Core Container

Core and Beans modules are the basic parts of the framework, providing IoC and dependency injection features
The core of ioc's idea is that resources are not managed by both parties who use resources, but by a third party who does not use resources, which can bring many benefits. First, centralized management of resources to realize the configurable and easy management of resources. Second, it reduces the dependence of both parties using resources, that is, the degree of coupling.

  • Core mainly contains the basic core tool classes of the Spring framework. Other components of Spring need to use the classes in this package.
  • Beans contains all classes related to accessing configuration files, creating and managing bean s, and performing (IoC/DI) operations
  • Context modeling is based on Core and Beans modules and provides a framework object access method similar to JNDI registrar. The context module inherits the characteristics of Beans, provides a large number of extensions for the Spring Core, and adds support for internationalization (such as resource binding), event propagation, resource loading and transparent creation of context. The context module also supports some J2EE features. The ApplicationContext interface is the key to the context module
  • The Expression Language module provides a powerful Expression Language for querying and manipulating objects at run time. It is an extension of the unifed expression language defined in the JSP 2.1 specification. The language supports setting / obtaining the value of attributes, attribute allocation, method call, accessing the context of arrays, containers and indexers, logical and arithmetic operators, named variables, and retrieving objects by name from the IoC container of Spring. It also supports list projection, selection, and general list aggregation

Spring container inheritance diagram

Spring IOC container bottom annotation usage

1. Form of XML configuration file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="person" class="com.yemuxia.ioc02.Person">
        <property name="id" value="1"/>
        <property name="name" value="Zhang San"/>
    </bean>
</beans>
package com.yemuxia.ioc02;


public class Person {

    private Integer id;
    private String name;
    public Person() {
        System.out.println("I'm a constructor");
    }

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

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

package com.yemuxia.ioc02;

import org.springframework.context.support.ClassPathXmlApplicationContext;


public class MainClass {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("XmlBean.xml");
        Person person = (Person)ctx.getBean("person");
        System.out.println(person);
    }
}

2. Define Bean information based on the form of reading configuration class

package com.yemuxia.ioc03;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfig {
    @Bean
    public Person person1(){
        return new Person();
    }
}

package com.yemuxia.ioc03;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;

public class MainClass {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);
        String[] beanNames = context.getBeanDefinitionNames();
        Arrays.stream(beanNames).forEach(System.out::println);
    }
}


If it is used in the form of @ bean, the default name of the bean is the method name. If @ Bean(value = "bean name"), the bean name is specified

3. Write @ CompentScan annotation on the configuration class to scan the package

package com.yemuxia.ioc01;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan("com.yemuxia.ioc01")
public class AppConfig {
}

package com.yemuxia.ioc01;

import org.springframework.stereotype.Controller;

@Controller
public class TestController {
}

package com.yemuxia.ioc01;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        String[] beanDefinationNames = context.getBeanDefinitionNames();
        for (String name:beanDefinationNames) {
            System.out.println("bean Definition information of:"+name);
        }
    }
}

Exclusion usage excludeFilters

package com.yemuxia.ioc01;

import org.springframework.stereotype.Service;

@Service
public class TestService {
}

package com.yemuxia.ioc01;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@ComponentScan(basePackages = "com.yemuxia.ioc01", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class}),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {TestService.class})
})
public class AppConfig {
}

Include usage includeFilters

Note that if you use the included usage, you need to set the useDefaultFilters property to false (true means to scan all)

package com.yemuxia.ioc01;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@ComponentScan(basePackages = "com.yemuxia.ioc01", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})
}, useDefaultFilters = false)
public class AppConfig {
}

@ComponentScan. Type of filter type

FilterType.CUSTOM custom type

package com.yemuxia.ioc01;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class TestFilterType implements TypeFilter {

    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //Gets the annotation source information of the current class
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

        //Gets the source information of the class of the current class
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //Gets the resource information of the current class
        Resource resource =  metadataReader.getResource();
        System.out.println("Path to class:"+classMetadata.getClassName());
        if(classMetadata.getClassName().contains("Dao")) {
            return true;
        }
        return false;
    }
}

package com.yemuxia.ioc01;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;

@ComponentScan(basePackages = "com.yemuxia.ioc01", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM,value = TestFilterType.class)
})
public class AppConfig {
}

4. Configure the scope object of the Bean

When @ Scope is not specified, all beans are single instance beans and are loaded (the container starts and the instance is created)

package com.yemuxia.ioc03;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class TestConfig {
    @Bean
    @Scope(value = "prototype")
    public Person person1(){
        return new Person();
    }
}


Specify @ Scope as prototype, which means it is multi instance and loaded in lazy mode (the object will not be created when the IOC container is started, but will be created when it is used for the first time)

@Scope specified scope method value

  • a) singleton single instance (default)
  • b) prototype multi instance
  • c) request same request
  • d) session the same session level
package com.yemuxia.ioc03;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

@Configuration
public class TestConfig {
    @Bean
    @Lazy
    public Person person1(){
        return new Person();
    }
}


Lazy loading @ lazy of beans (mainly for single instance beans. The object will not be created when the container is started, but will only be created when it is used for the first time)

5.@Conditional makes conditional judgment

package com.yemuxia.ioc04;

public class TestComponentA {
    public TestComponentA() {
        System.out.println("assembly A Construction method of");
    }
}

package com.yemuxia.ioc04;

public class TestComponentB {
    public TestComponentB() {
        System.out.println("assembly B Construction method of");
    }
}

package com.yemuxia.ioc04;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfig {
    @Bean
    public TestComponentA testComponentA(){
        return new TestComponentA();
    }

    @Bean
    @Conditional(value = TestCondition.class)
    public TestComponentB testComponentB(){
        return new TestComponentB();
    }
}

package com.yemuxia.ioc04;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;



public class TestCondition implements Condition {


    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //Determine whether there is a component of testComponentA in the container
        if(context.getBeanFactory().containsBean("testComponentA")) {
            return true;
        }
        return false;
    }
}

package com.yemuxia.ioc04;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);
        String[] beanNames = context.getBeanDefinitionNames();
        Arrays.stream(beanNames).forEach(System.out::println);
    }
}

package com.yemuxia.ioc04;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfig {
    //@Bean
    public TestComponentA testComponentA(){
        return new TestComponentA();
    }

    @Bean
    @Conditional(value = TestCondition.class)
    public TestComponentB testComponentB(){
        return new TestComponentB();
    }
}


If there is an instance of TestComponentA in the container, TestComponentB will be instantiated

6. How to add components to IOC container

  • Applicable scenario through @ compentscan + @ controller @ service @ repository @ compent: components written by ourselves can be loaded into the container in this way.
  • Import components through @ Bean (applicable to classes importing third-party components)
  • Import components through @ import (the id of the imported component is the full class name path)
  • The registered component is implemented by implementing the factorybean interface

Import components by @ import

package com.yemuxia.ioc5;


public class Car {
}

package com.yemuxia.ioc5;


public class Cat {
}

package com.yemuxia.ioc5;


public class Dog {
}

package com.yemuxia.ioc5;


public class Person {
}

package com.yemuxia.ioc5;


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 TestBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Cat.class);
        registry.registerBeanDefinition("cat",rootBeanDefinition);
    }
}

package com.yemuxia.ioc5;

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


public class TestImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.yemuxia.ioc5.Dog"};
    }
}

package com.yemuxia.ioc5;

import org.springframework.context.annotation.Import;



@Import(value = {Person.class, Car.class, TestImportSelector.class, TestBeanDefinitionRegister.class})
public class TestConfig {
}

package com.yemuxia.ioc5;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);
        String[] beanNames = context.getBeanDefinitionNames();
        Arrays.stream(beanNames).forEach(System.out::println);
    }
}

The registered component is implemented by implementing the factorybean interface

package com.yemuxia.ioc6;


public class Car {
}

package com.yemuxia.ioc6;

import org.springframework.beans.factory.FactoryBean;

/**
 * Register components in the container by implementing the FactoryBean interface
 */
public class CarFactoryBean implements FactoryBean<Car> {
    @Override
    public Car getObject() throws Exception {
        return new Car();
    }

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

    @Override
    public boolean isSingleton() {
        return false;
    }
}

package com.yemuxia.ioc6;

import org.springframework.beans.factory.FactoryBean;

import java.sql.DriverManager;


public class DriverFactoryBean implements FactoryBean {

    private String jdbcUrl;

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public void setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
    }

    @Override
    public Object getObject() throws Exception {
        return DriverManager.getDriver(jdbcUrl);
    }

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

    @Override
    public boolean isSingleton() {
        return true;
    }
}

package com.yemuxia.ioc6;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource(locations = {"classpath:beans.xml"})
public class AppConfig {
    @Bean
    public CarFactoryBean carFactoryBean(){
        return new CarFactoryBean();
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="com.yemuxia.ioc6.Car"/>

    <bean id="driverFactoryBean" class="com.yemuxia.ioc6.DriverFactoryBean">
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/yemuxia"/>
    </bean>

</beans>
package com.yemuxia.ioc6;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MainClass {

    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Object bean = ctx.getBean("carFactoryBean");
        System.out.println(bean);
        Object bean2 = ctx.getBean("&carFactoryBean");
        System.out.println(bean2);
        System.out.println(bean.getClass());
        System.out.println(bean2.getClass());
        Object bean3 = ctx.getBean("carFactoryBean");
        System.out.println(bean==bean3);

        CarFactoryBean carFactoryBean = ctx.getBean(CarFactoryBean.class);
        System.out.println(carFactoryBean);

        System.out.println(ctx.getBean("driverFactoryBean"));



    }
}

7.Bean initialization method and destruction method

What is the life cycle of a Bean

bean creation initialization destruction method
The container manages the life cycle of beans. We can specify the initialization method and destruction method of beans by ourselves.

  • For single instance beans, when the container starts, the bean object is created, and when the container is destroyed, the bean destruction method will also be called
  • For multi instance beans, when the container starts, the beans will not be created, but will be created when the beans are obtained, and the destruction of beans is not managed by the IOC container

Single instance bean demo

package com.yemuxia.ioc7;

public class Car {
    public Car() {
        System.out.println("Car Construction method of..........");
    }


    public void init() {
        System.out.println("Car Initialization method of......init");
    }

    public void destroy() {
        System.out.println("Car Destruction method of.....destroy");
    }
}

package com.yemuxia.ioc7;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@Configuration
@ComponentScan(basePackages = "com.yemuxia.ioc7")
public class AppConfig {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }


}

package com.yemuxia.ioc7;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);


        ctx.close();
    }
}

Multi instance bean

package com.yemuxia.ioc7;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
@ComponentScan(basePackages = "com.yemuxia.ioc7")
public class AppConfig {
    @Scope(value = "prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }


}

package com.yemuxia.ioc7;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Car car = ctx.getBean(Car.class);

        ctx.close();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(car);
    }
}

The initialization and destruction methods of beans are implemented through the two interfaces of InitializingBean and DisposableBean

package com.yemuxia.ioc7;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;


public class Person implements InitializingBean,DisposableBean {

    public Person() {
        System.out.println("Person Construction method of");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean of destroy()method ");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean of afterPropertiesSet method");
    }


}

package com.yemuxia.ioc7;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
@ComponentScan(basePackages = "com.yemuxia.ioc7")
public class AppConfig {
    @Scope(value = "prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }

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

}

Annotation methods of @ PostConstruct and @ ProDestory provided by JSR250 specification

package com.yemuxia.ioc7;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;


public class Book {

    public Book() {
        System.out.println("book Construction method of");
    }

    @PostConstruct
    public void init() {
        System.out.println("book of PostConstruct Marking method");
    }

    @PreDestroy
    public void destory() {
        System.out.println("book of PreDestory Annotation method");
    }
}

package com.yemuxia.ioc7;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
@ComponentScan(basePackages = "com.yemuxia.ioc7")
public class AppConfig {
    @Scope(value = "prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }

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

    @Bean
    public Book book(){
        return new Book();
    }
}

The post processor of beans through Spring's BeanPostProcessor will intercept all bean creation processes

  • postProcessBeforeInitialization is called before init method.
  • postProcessAfterInitialization is called after the init method.
package com.yemuxia.ioc7;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;


public class TestBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("TestBeanPostProcessor...postProcessBeforeInitialization:"+beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("TestBeanPostProcessor...postProcessAfterInitialization:"+beanName);
        return bean;
    }
}

package com.yemuxia.ioc7;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
@ComponentScan(basePackages = "com.yemuxia.ioc7")
public class AppConfig {
    @Scope(value = "prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }

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

    @Bean
    public Book book(){
        return new Book();
    }
    @Bean
    public TestBeanPostProcessor testBeanPostProcessor(){
        return new TestBeanPostProcessor();
    }
}


Execution timing of BeanPostProcessor

populateBean(beanName, mbd, instanceWrapper) 
initializeBean{ 
	applyBeanPostProcessorsBeforeInitialization() 
	invokeInitMethods{ 
		isInitializingBean.afterPropertiesSet 
		Custom init method 
	}
	applyBeanPostProcessorsAfterInitialization()method 
}

8. Assign values to components through @ Value and @ PropertySource

package com.yemuxia.ioc8;

import org.springframework.beans.factory.annotation.Value;



public class Person {

    @Value("Sima")
    private String firstName;

    @Value("#{28-8}")
    private Integer age;

    @Value("${person.lastName}")
    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public Integer getAge() {
        return age;
    }

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

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", age=" + age +
                ", lastName='" + lastName + '\'' +
                '}';
    }
}
person.lastName=Old thief
package com.yemuxia.ioc8;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource(value = {"classpath:person.properties"})
public class AppConfig {

    @Bean
    public Person person() {
        return new Person();
    }
}
package com.yemuxia.ioc8;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;



public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

        Person person = ctx.getBean(Person.class);
        System.out.println(person.toString());
    }
}

9. Automatic assembly

Automatic assembly is first assembled according to the type. If multiple components of the same type are found in the IOC container, it is assembled according to the attribute name

Assemble by type

package com.yemuxia.ioc9;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;


@ComponentScan(basePackages = {"com.yemuxia.ioc9"})
public class AppConfig {
    @Bean
    public TestDao testDao2() {
        TestDao testDao = new TestDao();
        testDao.setFlag(2);
        return testDao;
    }
}


package com.yemuxia.ioc9;


public class TestDao {

    private int flag=1;

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "TestDao{" +
                "flag=" + flag +
                '}';
    }
}
package com.yemuxia.ioc9;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;



@Service
public class BaiDuService {


    @Autowired
    private TestDao testDao;

    @Override
    public String toString() {
        return "BaiDuService{" + testDao +
                '}';
    }
}

package com.yemuxia.ioc9;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

        //byName or byType is used when testing @ AutoWired (byType is used by default, and byName is used when multiple bean s of the same type are found)
        //You need to specify the name of the assembly. Specify the assembly name through @ Qualifier
        BaiDuService baiDuService = ctx.getBean(BaiDuService.class);
        System.out.println(baiDuService);

    }
}

Assemble by property (multiple bean s of the same type)

package com.yemuxia.ioc9;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;


@ComponentScan(basePackages = {"com.yemuxia.ioc9"})
public class AppConfig {
    @Bean
    public TestDao testDao2() {
        TestDao testDao = new TestDao();
        testDao.setFlag(2);
        return testDao;
    }
    @Bean
    public TestDao testDao3() {
        TestDao testDao = new TestDao();
        testDao.setFlag(3);
        return testDao;
    }
}


This code reports an error. The reason for the error is that there are multiple bean instances of the same type in the Spring container, which will be assembled according to the instance name during automatic assembly. However, no matching instance name (testDao) was found in the container. Therefore, an error is reported.
If we do not find a matching instance name in the container, an exception will be thrown during assembly tuling. testautowired. Turing Dao 'available if we don't want to throw exceptions, we need to specify required as false

Use @ Qualifier("testDao") to specify the assembled components

package com.yemuxia.ioc9;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;



@Service
public class BaiDuService {


    @Autowired
    @Qualifier(value = "testDao3")
    private TestDao testDao;

    @Override
    public String toString() {
        return "BaiDuService{" + testDao +
                '}';
    }
}

Add the @ Primary annotation to the @ Bean on the configuration class

package com.yemuxia.ioc9;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Primary;


@ComponentScan(basePackages = {"com.yemuxia.ioc9"})
public class AppConfig {
    @Bean
    public TestDao testDao2() {
        TestDao testDao = new TestDao();
        testDao.setFlag(2);
        return testDao;
    }
    @Bean
    @Primary
    public TestDao testDao3() {
        TestDao testDao = new TestDao();
        testDao.setFlag(3);
        return testDao;
    }
}


@The difference between Autowired, @ Resource, @ Inject:

  • 1. @ Autowired comes with spring, @ Inject is implemented by JSR330 specification, @ Resource is implemented by JSR250 specification, and different packages need to be imported
  • 2. The usage of @ Autowired and @ Inject are basically the same, except that @ Autowired has a request attribute
  • 3. @ Autowired and @ Inject are matched by type by default, and @ Resource is matched by name
  • 4. @ Autowired needs to be used with @ Qualifier if it needs to match by name, @ Inject and @ Named

10. When the components written by yourself need to use the underlying components of spring ioc, such as ApplicationContext, etc

We can do this by implementing the XXXAware interface

package com.yemuxia.ioc10;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@Configuration
@ComponentScan(basePackages = "com.yemuxia.ioc10")
public class AppConfig {
}

package com.yemuxia.ioc10;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;


@Component
public class TestCompent implements ApplicationContextAware,BeanNameAware {

    private ApplicationContext applicationContext;

    @Override
    public void setBeanName(String name) {
        System.out.println("current bean name is :["+name+"]");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

package com.yemuxia.ioc10;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

    }
}

11. Activate and identify different beans according to the environment through @ Profile annotation

@If the Profile is identified on the class, the entire configuration class will take effect only if the current environment matches @ if the Profile is identified on the Bean, only the Bean of the current environment will be activated
No bean marked @ Profile can be activated in any environment

package com.yemuxia.ioc11;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;

import javax.sql.DataSource;

@Configuration
@PropertySource(value = {"classpath:ds.properties"})
public class AppConfig implements EmbeddedValueResolverAware {

    @Value("${ds.username}")
    private String userName;

    @Value("${ds.password}")
    private String password;

    private String jdbcUrl;

    private String classDriver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.jdbcUrl = resolver.resolveStringValue("${ds.jdbcUrl}");
        this.classDriver = resolver.resolveStringValue("${ds.classDriver}");
    }

    @Bean
    @Profile(value = "test")
    public DataSource testDs() {
        return buliderDataSource(new DruidDataSource());
    }

    @Bean
    @Profile(value = "dev")
    public DataSource devDs() {
        return buliderDataSource(new DruidDataSource());
    }

    @Bean
    @Profile(value = "prod")
    public DataSource prodDs() {
        return buliderDataSource(new DruidDataSource());
    }

    private DataSource buliderDataSource(DruidDataSource dataSource) {
        dataSource.setUsername(userName);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(classDriver);
        dataSource.setUrl(jdbcUrl);
        return dataSource;
    }
}

ds.username=root
ds.password=123456
ds.jdbcUrl=jdbc:mysql://localhost:3306/skq
ds.classDriver=com.mysql.jdbc.Driver
package com.yemuxia.ioc11;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.getEnvironment().setActiveProfiles("test","dev");
        ctx.register(AppConfig.class);
        ctx.refresh();
        printBeanName(ctx);
    }

    private static void printBeanName(AnnotationConfigApplicationContext ctx){
        for(String beanName:ctx.getBeanDefinitionNames()) {
            System.out.println("In container BeanName: "+beanName);
        }
    }

}


Method of activating switching environment

  • Method 1: switch through runtime jvm parameters
    -Dspring.profiles.active=test|dev|prod
  • Method 2: activate by code

Keywords: Spring

Added by gclx on Wed, 19 Jan 2022 10:46:47 +0200