Spring annotation - life cycle, attribute assignment, auto assembly

1, Bean's life cycle

Technological process

Bean creation - initialization - Destruction

Establish:

  • Single instance: creating objects when container starts
  • Multiple instances: creating objects on each call

Initialization:

  • After the object is created, the initialization method is called

Destruction:

  • Single instance: call destroy method when container is closed
  • Multi instance: the container will not manage this bean, it can only call the destroy method manually

Realization way

  1. stay @Bean Initmethod and destroymethod are specified on the annotation

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
    
  2. Let beans implement the InitializingBean and DisposableBean interfaces and override their methods

    public class Cat implements InitializingBean, DisposableBean {
        public Cat() {
            System.out.println("Cat...Construct...");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("Cat...init...");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("Cat...destroy...");
        }
    }
    
  3. Annotate initialization and destruction methods with @ PostConstruct and @ PreDestroy annotations in JSR250

    public class Dog {
        public Dog() {
            System.out.println("Dog...Construct...");
        }
    
        @PostConstruct
        public void init(){
            System.out.println("Dog...init...");
        }
    
        @PreDestroy
        public void destroy(){
            System.out.println("Dog...destroy...");
        }
    }
    
  4. Implement the BeanPostProcessor interface, rewrite

    Post process before initialization

    postProcessAfterInitialization (works after initialization)

    public class MyBeanPostProcessor implements BeanPostProcessor {
     @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessBeforeInitialization" + beanName);
            return bean;
        }
    
     @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessAfterInitialization" + beanName);
            return bean;
        }
    }
    

2, Comment on attribute assignment

@Value

Effect:

Added to a field to assign a value to a property

Properties:

  • Value: Specifies the value to pass in

Usage:

public class Person {
    @Value("Zhang San") //Assignment in normal way
    private String name;
    
    @Value("#{20 - 1} ") / / use the spiel expression
    private Integer age;
    
    @Value("${person.nickName}") //Use ${} to read the contents of the configuration file
    private String nickName;
    
    //Omit getter setter toString method
}

The third way is obviously unreadable. We need to configure the location of the configuration file and use the following annotation

@PropertySource

Effect:

Read the specified external configuration file, save the K/V key value pair to the running environment variable, and use ${} to get it

Properties:

  • Name: specify a name for the attribute source
  • value: the path of the configuration file to be loaded. You can specify multiple
  • Ignore resource not found: whether to ignore the condition that the resource is not found, default false
  • Encoding: the specific character encoding of a given resource, such as "UTF-8"
  • Factory: specifies a custom property source factory, using PropertySourceFactory by default

Usage:

Create a properties file in the resources directory as follows

person.nickName = Xiao Zhang

Then mark @ PropertySource("classpath:person.properties") on the configuration class

You can get it directly in the @ Value annotation or through the ioc container object

ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration4.class);
String nickName = context.getEnvironment().getProperty("person.nickName");
System.out.println(nickName);

3, Auto assembly related notes

Spring uses dependency injection (DI) to complete the dependency assignment of various components in the IOC container

@Autowired

  • By default, search for the corresponding component in the container according to the type. If there is only one, assign the value

  • If more than one component of the same type is found, then search by property name

  • There is a required attribute, which is true by default;

  • It can be written on the constructor, method, parameter and attribute

@Qualifier

  • Generally used with @ Autowired, specify the id of the component to be assembled, and @ Autowired will inject directly according to the id.
  • If the component corresponding to id does not exist and required = false is not specified, an error will be reported

@Primary

  • When Spring is asked to automatically assemble, first select the component labeled @ Primary
  • If @ Qualifier has been used to indicate the component to be assembled, it will not take effect

A kind of Two less commonly used auto injection annotations:

@Resource(JSR250)

  • Annotations in the java specification can be automatically assembled just like @ Autowired
  • The variable name is used as the id by default and cannot be used with @ Qualifier @Primary

@Inject(JSR330)

The same as @ Autowired, but without the required attribute, you need to import the jar package of javax.inject

<dependency>
    <groupid>javax.inject</groupid>
    <artifactid>javax.inject</artifactid>
    <version>1</version>
</dependency>

@Profile

  • Specifies the environment in which the component is registered in the container. If it is not specified, it is registered in any environment

  • Multiple environments can be specified, and default is the default environment

  • Can be written on the configuration class

You can also specify the environment by code

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration5.class);
applicationContext.getEnvironment().setActiveProfiles("prod");

4, Using Spring container underlying components

For custom components, if you want to use the underlying components of Spring container, you can implement the sub interface (xxxAware) of the Aware interface, as shown in the following figure

@Component
public class TestAware implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Afferent IOC Container:" + applicationContext);
        this.applicationContext = applicationContext;
    }
}

All the functions of xxxAware are processed by ApplicationContextAwareProcessor

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	@Nullable
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &amp;&amp;
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<object>) () -&gt; {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

    //Inject different components into the bean according to the type of the incoming bean
	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}
```</object>

Tags: Programming Attribute Spring encoding less

Posted on Wed, 18 Mar 2020 05:38:08 -0700 by jay7981