directory

  • 1. The basic
  • 2. Xml-based configuration of IOC
  • 3. Annotations based configuration of IOC
  • 4. Concepts related to AOP
  • 6. The spring into the order
  • 7. Message monitoring mechanism
  • 8. Behavior of things control and dissemination
  • 9. The Spring source code
  • 10. The Spring lifecycle

The Spring life cycle is related to multiple interfaces, and the entire Spring life cycle is managed by Spring.

1. Initialization and destruction methods of bean objects

Bean object initialization method: After the bean object’s instantiation (default constructor), initialization (set method) is executed, Spring displays the method called. There are three main ways to declare:

  • Add init-method to the tag
<bean class=Introduction to "com. Qunar. Spring. Pojo. User3." " id="user3" init-method="start">
Copy the code
  • Annotate the bean-defined methods with @postconstruct annotations
public class User2{
    private Integer userId;
   
    public User2(a){
        System.out.println("Constructor");
    }
    
    @PostConstruct
    void printInfo(a) {
        System.out.println("user2");
    }

Copy the code
  • Implement the InitializingBean interface and override the afterPropertiesSet() method
public class User2 implements InitializingBean{
    private Integer userId;

    public User2(a){
        System.out.println("Constructor");
    }
    @Override
    public void afterPropertiesSet(a) throws Exception {
        System.out.println("after"); }}Copy the code

The order of execution is constructor >> @postconstruct or Constructor >>afterPropertiesSet()>>init-method.

Bean object destruction methods: The spring container’s callback method before the destruction method is executed. There are also three destruction callback methods:

  • Only destory-method is used to specify the callback method in the tag
	<bean class="com.dpb.pojo.User" id="user" init-method="start" destroy-method="end">
Copy the code
  • Override the deStory method by implementing the DisposableBean interface
public class AnotherExampleBean implements DisposableBean {
 
    public void destroy(a) {
        // do some destruction work (like releasing pooled connections)}}Copy the code
  • @ PreDestory annotations
	@PreDestroy
	public  void preDestory(a){
		System.out.println("--preDestory---");
	}
Copy the code

Order: @predeStory Container destruction or: deStory ()>>destory-method>> Container destruction.

2. Aware interface

By implementing the Aware interface, beans can access the Spring container. * These Aware methods are executed after the object is instantiated, after properties are injected into the bean, and before custom initialization methods

2.2 Common Aware Interfaces

2.1ApplicationContextAware
void setApplicationContext(ApplicationContext applicationContext)2.2 BeanClassLoaderAwarevoid setBeanClassLoader(ClassLoader classLoader);

2.3BeanFactoryAware
void setBeanFactory(BeanFactory beanFactory)2.4 BeanNameAwarevoid setBeanName(String name);
Copy the code

Through the Aware interface, you can be Aware of spring container information when a bean is loaded into the Spring container and set this information into bean objects

** * Implements the ApplicationContextAware * BeanClassLoaderAware * BeanFactoryAware * BeanNameAware * interface@author dengp
 *
 */
public class User implements ApplicationContextAware.BeanClassLoaderAware.BeanFactoryAware.BeanNameAware{

	private int id;
	
	private String name;
	// Save the perceived information
	private String beanName;
	// Save the perceived information
	private BeanFactory beanFactory;
	// Save the perceived information
	private ApplicationContext ac;
	// Save the perceived information
	private ClassLoader classLoader;
	
	public BeanFactory getBeanFactory(a) {
		return beanFactory;
	}

	public ApplicationContext getAc(a) {
		return ac;
	}

	public ClassLoader getClassLoader(a) {
		return classLoader;
	}

	public User(a){
		System.out.println("User is instantiated");
	}

	public int getId(a) {
		return id;
	}

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

	public String getName(a) {
		return name;
	}

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

	public String getBeanName(a) {
		return beanName;
	}
	
	/** * Custom initialization method */
	public void start(a){
		System.out.println("Custom initialization methods in User");
	}
	
	@Override
	public String toString(a) {
		return "User [id=" + id + ", name=" + name + ", beanName=" + beanName + "]";
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		System.out.println(">>> setBeanClassLoader");
		this.classLoader = classLoader;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println(">>> setApplicationContext");
		this.ac = applicationContext;
	}

	@Override
	public void setBeanName(String name) {
		System.out.println(">>> setBeanName");
		this.beanName = name;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println(">>> setBeanFactory");
		this.beanFactory = beanFactory; }}Copy the code

The test class:

@Test
public void test1(a) {
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	User user = ac.getBean(User.class);
	System.out.println("beanFactory:"+user.getBeanFactory());
	System.out.println("beanName:"+user.getBeanName());
	System.out.println("applicationContext:"+user.getAc());
	System.out.println("classLoader:"+user.getClassLoader());
	System.out.println(user);
}
Copy the code

Output result:

User is instantiated >>> setBeanName >>> setBeanClassLoader >>> setBeanFactory >>> setApplicationContext custom initialization method in User beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@4520ebad: defining beans [user]; root of factory hierarchy beanName:user applicationContext:org.springframework.context.support.ClassPathXmlApplicationContext@311d617d: startup date [Sun Mar 03 22:43:08 CST 2019]; The root of the context hierarchy this: sun. Misc. The Launcher $AppClassLoader @ 4 aa298b7 User [id = 0, name = bobo roast duck, beanName = User]Copy the code

3. The BeanPostProcessor interface

BeanPostProcessor is also called a post-processor. BeanPostProcessor can display the source code of the BeanProcessor interface before and after the invocation of custom initialization methods after bean instantiation and dependency injection

public interface BeanPostProcessor {
	// before the custom init method
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    // execute after the custom init method
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
Copy the code

– (I) The use of BeanPostProcessor

The BeanPostProcessor interface is: * We can add our own logic before and after bean instantiation, configuration, and other initialization methods */
public class MyBeanPostProcessor implements BeanPostProcessor {

    /** * Complete some custom initialization tasks before calling display initialization * Note: Method return value cannot be null * If null is returned then subsequent initializers will either report a null pointer exception or the bena instance object cannot be retrieved through the getBean() method */ because the backend handler took the bean instance object from the Spring IoC container and did not put it back into the IoC container */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Before -- instantiated bean object :"+bean+"\t"+beanName);
        // Different processing operations can be performed depending on the beanName
        return bean;
    }

    /** * execute when instantiation, dependency injection, and initialization are complete Method return value cannot be null * If null is returned then subsequent initializers will either report a null pointer exception or the bena instance object cannot be retrieved through the getBean() method */ because the backend handler took the bean instance object from the Spring IoC container and did not put it back into the IoC container */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("after... Instantiated bean object :"+bean+"\t"+beanName);
        // Different processing operations can be performed depending on the beanName
        returnbean; }}Copy the code
public class User3 {

    private int id;

    private String name;

    private String beanName;

    public User3(a){
        System.out.println("User is instantiated");
    }

    public int getId(a) {
        return id;
    }

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

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        System.out.println("Setup:"+name);
        this.name = name;
    }

    public String getBeanName(a) {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
    /** * Custom initialization method */
    public void start(a){
        System.out.println("Custom initialization methods in User");
    }

    @Override
    public String toString(a) {
        return "User3{" +
                "id=" + id +
                ", name='" + name + '\' ' +
                ", beanName='" + beanName + '\' ' +
                '} '; }}Copy the code

XML configuration, add PostPostPrecessor to the container

 <bean class=Introduction to "com. Qunar. Spring. Pojo. User3." " id="user3" init-method="start">
        <property name="name" value="Bobo Duck" />
    </bean>

    <! -- Register handler -->
    <bean class=Introduction to "com. Qunar. Spring. Pojo. MyBeanPostProcessor"></bean>
Copy the code

Execution Result:

User3{id=0, name=' bobo ', beanName='null'} User3{id=0, beanName='null'} User3{id=0, beanName='null'} BeanName ='null'} User3 User3{id=0, name=' bobo ', beanName='null'}Copy the code

You can also set up multiple Beanpostprocessors, which will be called in the declared order by default. You can also implement the Ordered interface, which implements the getOrder() method to specify the order. In the Spring mechanism, you can specify the post-processor call order. The Ordered interface getOrder method is implemented by having the BeanPostProcessor interface implementation class. The Ordered interface getOrder method returns an integer with a default value of 0 and the highest priority

public class MyBeanPostProcessor implements BeanPostProcessor.Ordered{
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

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

	@Override
	public int getOrder(a) {
		// TODO Auto-generated method stub
		return 10; }}Copy the code

4. InstantiationAwareBeanPostProcessor interface

InstantiationAwareBeanPostProcessor interface BeanPostProcesso as part of the interface, the main role is the perception of the bean instantiation, in before, during and after the bean instantiation object’s properties before injection for related operation;

Interface source code

package org.springframework.beans.factory.config;
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	Object postProcessBeforeInstantiation(Class
        beanClass, String beanName) throws BeansException;

	boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

	PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}
Copy the code

What we can learn from the source code is that the interface defines three additional methods of its own in addition to the two methods in the parent interface. Therefore, the interface defines five methods. The functions of these five methods are

methods describe
postProcessBeforeInitialization Methods in the BeanPostProcessor interface that are executed before the Bean’s custom initialization methods
postProcessAfterInitialization Methods in the BeanPostProcessor interface are executed after the Bean’s custom initialization method has been executed
postProcessBeforeInstantiation Its own method, which is the first method to execute, is called before the target Object is instantiated, and its return value type is Object, so we can return any type of value. Since the target object is not instantiated at this time, the return value can be used instead of the instance of the target object (such as the proxy object) that should have been generated. If the return value of this method instead of the originally generated by the target object, and the follow-up only postProcessAfterInitialization method is invoked, other methods are no longer called; Otherwise, follow the normal procedure
postProcessAfterInstantiation Called after the target object is instantiated, when the object has been instantiated, but the instance properties have not been set, which are null. Because it is the return value is decided to don’t call postProcessPropertyValues method is one of the factors (because there is another factor is MBD getDependencyCheck ()); If this method returns false, and do not need to check, then postProcessPropertyValues will be ignored no execution; If returns true, postProcessPropertyValues will be executed
postProcessPropertyValues To modify attribute values, if postProcessAfterInstantiation method returns false, this method may not be invoked. Property values can be modified within this method

Example:

/** * Custom processor *@author dengp
 *
 */
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{

	/** * Methods in the BeanPostProcessor interface * execute before the Bean's custom initialization method * The Bean object already exists */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println(">>postProcessBeforeInitialization");
		return bean;
	}

	/** * Methods in the BeanPostProcessor interface * execute after the Bean's custom initialization method has completed * the Bean object already exists */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("<<postProcessAfterInitialization");
		return bean;
	}

	/ custom methods of * * * * InstantiationAwareBeanPostProcessor before methods instantiate execution Bean object has not been * /
	@Override
	public Object postProcessBeforeInstantiation(Class
        beanClass, String beanName) throws BeansException {
		System.out.println("--->postProcessBeforeInstantiation");
		return null;
	}

	/ custom methods of * * * * InstantiationAwareBeanPostProcessor after methods instantiate execution Bean object has been created * /
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		System.out.println("<---postProcessAfterInstantiation");
		return true;
	}

	/ custom methods of * * * * InstantiationAwareBeanPostProcessor can be used to modify the content of the Bean attribute * /
	@Override
	public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
		System.out.println("<---postProcessPropertyValues--->");
		returnpvs; }}Copy the code

The target object

public class User {

	private int id;
	
	private String name;
	
	private String beanName;
	
	public User(a){
		System.out.println("User is instantiated");
	}

	public int getId(a) {
		return id;
	}

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

	public String getName(a) {
		return name;
	}

	public void setName(String name) {
		System.out.println("Setup:"+name);
		this.name = name;
	}

	public String getBeanName(a) {
		return beanName;
	}

	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}
	public void start(a){
		System.out.println("Custom initialization method....");
	}
	
	@Override
	public String toString(a) {
		return "User [id=" + id + ", name=" + name + ", beanName=" + beanName + "]"; }}Copy the code

The configuration file


      
<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 class="com.dpb.pojo.User" id="user" init-method="start">
		<property name="name" value="Bobo Duck"></property>
	</bean>
	
	<! - registered InstantiationAwareBeanPostProcessor object - >
	<bean class="com.dpb.processor.MyInstantiationAwareBeanPostProcessor"></bean>
</beans>
Copy the code

test

@Test
public void test1(a) {
	ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	User user = ac.getBean(User.class);
	System.out.println(user);
	// Close destruction
	ac.registerShutdownHook();
}

Copy the code

Test results:

- > postProcessBeforeInstantiation User is instantiated < - postProcessAfterInstantiation < - postProcessPropertyValues - > Settings: Bobo duck > > postProcessBeforeInitialization custom initialization method... < < postProcessAfterInitialization User id = 0, name = bobo roast duck, beanName = null]Copy the code

Description:

  1. If postProcessBeforeInstantiation returns null; The bean object is modified. In the middle of the instantiated and initialization before execution, direct execution postProcessAfterInitialization method;

2. PostProcessAfterInstantiation return value should pay attention to, because it is the return value is decided to don’t call postProcessPropertyValues method is one of the factors; If this method returns false, and do not need to check, then postProcessPropertyValues will be ignored no execution; If return true, will be performed 3 postProcessPropertyValues. In populateBean approach we have seen the postProcessPropertyValues executive position

An example of postPorcessPropertyValues execution

/ * * * InstantiationAwareBeanPostProcessor custom method Can be used to modify the content of the Bean attribute * /
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
	System.out.println("<---postProcessPropertyValues--->");
	if(bean instanceof User){
		PropertyValue value = pvs.getPropertyValue("name");
		System.out.println("The value of name before modification was :"+value.getValue());
		value.setConvertedValue("bobo");
	}
	return pvs;
}
Copy the code

5. Spring BeanFactoryPostProcessor interface

The BeanactoryPostProcessor interface allows you to change the bean definition information before any bean is instantiated by the Spring container. You can define multiple BeanFactoryPostProcessor classes and determine the Order of execution from the return value of the Order interface.

Sample implementation interface

/** * Custom BeanFactoryPostProcessor **@author dengp
 *
 */
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	/** * This method is executed before the Bean object is instantiated. The beanFactory is used to obtain the Bean definition information, and the Bean definition information can be modified. This is the biggest difference from BeanPostProcessor */
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		
		System.out.println(>> BeanFactoryPostProcessor is running);
		String[] names = beanFactory.getBeanDefinitionNames();
		for (String name : names) {
			if("user".equals(name)){
				
				BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
				MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
				// MutablePropertyValues Can be modified if the properties are set, or added if they are not
				if(propertyValues.contains("name")){
					propertyValues.addPropertyValue("name"."bobo");
					System.out.println("Modified attribute information");
				}
			}
		}
		System.out.println(">> BeanFactoryPostProcessor execution completed"); }}Copy the code

The configuration file


      
<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 class="com.dpb.pojo.User" id="user" init-method="start">
		<property name="name" value="Bobo Duck"></property>
	</bean>
	
	<! -- Register handler -->
	<bean class="com.dpb.processor.MyBeanPostProcessor"/>
	<! BeanFactoryPostProcessor -->
	<bean class="com.dpb.factoryprocessor.MyBeanFactoryPostProcessor"></bean>
</beans>
Copy the code

The main program

@Test
public void test1(a) {
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	User user = ac.getBean(User.class);
	System.out.println(user);
}
Copy the code

The output

>> BeanFactoryPostProcessor Starts executing. Modified properties. >> BeanFactoryPostProcessor Ends. Bobo A before-- instantiated bean object :User [id=0, name=bobo, beanName=null] User User [id=0, name=bobo, beanName=null] User User [id=0, name=bobo, beanName=null]Copy the code

6. Summary

Example:

public classtestspringLife cycle object ofimplements InitializingBean.DisposableBean , BeanNameAware {

    // Own attribute value
    private int id;
    private String name;
    private String beanName;

    public int getId(a) {
        return id;
    }

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

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        System.out.println("Property injection");
        this.name = name;
    }

    publicTest Spring's lifecycle object (){system.out.println ("Instantiate");
    }

    @PostConstruct
    public void start1(a){
        System.out.println("Executive postConstruct");
    }

    public void start2(a) {
        System.out.println("Execute init-method method");
    }

    @Override
    public void afterPropertiesSet(a) throws Exception {
        System.out.println("Executive afterPropertiesSet");
    }

    @Override
    public void destroy(a) throws Exception {
        System.out.println("Executive destroy");
    }

    public void end2(a) {
        System.out.println("Executive destory - method");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("Implement aware method");
        this.beanName=name; }}Copy the code

InstantiationAwareBeanPostProcessor interface implementation class

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class
        beanClass, String beanName) throws BeansException {
        System.out.println("Executive postProcessBeforeInstantiation method");
        //return new User();
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("Executive postProcessAfterInstantiation");
        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("Executive postProcessPropertyValues");
        return pvs;
    }

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

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Executive postProcessAfterInitialization");
        returnbean; }}Copy the code

The configuration file

    <! -- Register handler -->
    <bean id="springbean" class="Com.qunar. Spring getting started. Pojo. testing Spring lifecycle objects" init-method="start2" destroy-method="end2">
        <property name="name" value="The first name"></property>
    </bean>
    <! Registered - - - >
    <bean id="myBeanFactoryPostProcessor" class=Introduction to "com. Qunar. Spring. Pojo. MyBeanFactoryPostProcessor"></bean>
    <bean id="myBeanFactoryPostProcessor2" class=Introduction to "com. Qunar. Spring. Pojo. MyBeanFactoryPostProcessor2"></bean>

    <bean id="myInstantiationAwareBeanPostProcessor" class=Introduction to "com. Qunar. Spring. Pojo. MyInstantiationAwareBeanPostProcessor"></bean>
Copy the code

The test class

public classtestspringLife cycle of{
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring lifecycle.xml"); Test object b = spring's life cycle (test object) spring's life cycle applicationContext. GetBean ("springbean"); System.out.println(b.getName()); applicationContext.close(); }}Copy the code

Output result:

PostProcessBeanFactory2 executed postProcessBeanFactory method to modify the property value method And modify the instantiated attribute value postProcessBeforeInstantiation execution method Perform postProcessAfterInstantiation postProcessPropertyValues attributes inject postProcessBeforeInitialization executed aware method Perform the afterPropertiesSet init - method method performs postProcessAfterInitialization executed destroy the third name destory - method Process finished with exit code 0Copy the code