Spring Bean life cycle collation

Posted by JMulligan on Wed, 22 Dec 2021 10:24:56 +0100

Main process


Classification of various interface methods

The complete life cycle of a Bean has experienced various method calls, which can be divided into the following categories:

  1. Bean's own methods include the methods called by the bean itself and the methods specified through the init method and destroy method of < bean > in the configuration file

  2. Bean level life cycle interface method: This includes methods of BeanNameAware, BeanFactoryAware, InitializingBean and DiposableBean interfaces

  3. Container level life cycle interface method: This includes two interface implementations, instantiawarebeanpostprocessor and BeanPostProcessor. Their implementation classes are generally called "postprocessor".

  4. Factory postprocessor interface method: This includes aspectjweavinginabler, configurationclasspostprocessor, customautowireconfigurator and other very useful factory postprocessor interface methods. The factory post processor is also container level. Called immediately after the context assembly profile is applied.

  5. The scope of the BeanFactoryPostProcessor interface and the BeanPostProcessor interface is to add a new class to implement these interfaces in the whole context. Then, at some time when other beans are processed, the methods in the response interface will be called back.

  6. The scope of action of BeanNameAware, beanfactory aware and ApplicationContextAware is the Bean scope, that is, it is only valid for the specified Bean that implements the interface. All its usage methods are to implement the interface by the Bean that wants to use the function.

demonstration

1. The first is a simple Spring Bean, which calls Bean's own methods and Bean level life cycle interface methods. To facilitate demonstration, it implements five interfaces: BeanNameAware, ApplicationContextAware, BeanFactoryAware, InitializingBean and DiposableBean. At the same time, it has two methods, corresponding to the init method and destroy method of < Bean > in the configuration file. As follows:

@Component
public class BizPerson implements Person, BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
    private Animal animal;

    @Override
    public void service() {
        animal.use();
    }

    @Override
    @Autowired
    @Qualifier("cat")
    public void setAnimal(Animal animal) {
        System.out.println("Delayed dependency injection");
        this.animal = animal;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println(this.getClass().getSimpleName() + "call BeanNameAware of setBeanName method");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println(this.getClass().getSimpleName() + "call BeanFactoryAware of setBeanFactory method");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(this.getClass().getSimpleName() + "call ApplicationContextAware of setApplicationContext method");
    }

    @PostConstruct
    public void init() {
        System.out.println(this.getClass().getSimpleName() + "call@PostConstruct Custom initialization method");
    }

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

    @PreDestroy
    public void destroy1() {
        System.out.println(this.getClass().getSimpleName() + "call@PreDestroy Custom destruction method");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass().getSimpleName() + "call DisposableBean of destroy method");
    }
}
public interface Animal {
    void use();
}

@Component
public class Cat implements Animal, BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
    @Override
    public void use() {
        System.out.println("Cat[" + Dog.class.getSimpleName() + " ]It's for catching mice.");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println(this.getClass().getSimpleName() + "call BeanFactoryAware of setBeanFactory method");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println(this.getClass().getSimpleName() + "call BeanNameAware of setBeanName method");
    }

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

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

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(this.getClass().getSimpleName() + "call ApplicationContextAware of setApplicationContext method");
    }

    @PostConstruct
    public void init() {
        System.out.println(this.getClass().getSimpleName() + "call@PostConstruct Custom initialization method");
    }

    @PreDestroy
    public void destroy1() {
        System.out.println(this.getClass().getSimpleName() + "call@PreDestroy Custom destruction method");
    }
}

@Component
@Primary
public class Dog implements Animal {
    @Override
    public void use() {
        System.out.println("Dog[" + Dog.class.getSimpleName() + " ]It's for the doorman.");
    }
}
@Configuration
@ComponentScan(lazyInit = true)
public class AppConfig {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        BizPerson bean = annotationConfigApplicationContext.getBean(BizPerson.class);
        bean.service();
        annotationConfigApplicationContext.registerShutdownHook();
    }
}

The results are as follows:

  1. The next step is to demonstrate the methods of the BeanPostProcessor interface, as follows:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization()--before->"+"initialization beanName:"+beanName);
        return bean;
    }

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

Execution results:

As mentioned above, the BeanPostProcessor interface includes two methods, postProcessAfterInitialization and postProcessBeforeInitialization. The first parameter of these two methods is the Bean object to be processed, and the second parameter is the name of the Bean. The return values are also Bean objects to be processed.

  1. The instantiawarebeanpostprocessor interface is essentially a sub interface of BeanPostProcessor. Generally, we inherit the adapter class instantiawarebeanpostprocessor adapter provided by Spring to use it, as follows:
@Component
public class MyInstantiationAwareBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter {

    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("This is InstantiationAwareBeanPostProcessorAdapter Implement class constructor!!");
    }

    // The interface method and the instantiation of Bean are called before.
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,
                                                 String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor call postProcessBeforeInstantiation method");
        return null;
    }

    // After the interface method is instantiated, Bean is called.
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor call postProcessAfterInitialization method");
        return bean;
    }

    // Interface method, called when setting a property
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                                                    PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor call postProcessPropertyValues method");
        return pvs;
    }
}

The results are as follows:

The second method, postProcessAfterInitialization, overrides the method of BeanPostProcessor. postProcessPropertyValues is used to manipulate properties, and the return value should also be a PropertyValues object.

  1. Demonstrate the factory post processor interface method as follows
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("This is BeanFactoryPostProcessor Implement class constructor!!");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
            throws BeansException {
        System.out
                .println("BeanFactoryPostProcessor call postProcessBeanFactory method");
        BeanDefinition bd = arg0.getBeanDefinition("cat");
        bd.getPropertyValues().addPropertyValue("name", "110");
    }

}