Life of bean

Keywords: Java Spring mvc

When ssm comes. First spring will be found. Why?

Because we need to hand over objects to srping for unified management,

Let's review the two main features of spring

ioc

We've worked with spring to help us create classes and decouple between our classes

aop

Some enhancements can be added without changing the source code of the class, such as front, rear, exception, and so on.

When we want to use the framework to achieve more and more functions, we often need to fill in many and many bean components, so we can use the classes in the ioc container directly.

Post Processors

There are also differences in creating classes

  • There are instances of factory creation
  • Creation with bean s

All of these require a corresponding postprocessor, so let's take a look at Spring's flexibility in providing us with processors that execute postprocessors when bean s injected into containers are about to be initialized and then put into spring's pool.

Processors for bean s

BeanPostProcessor: Bean's postprocessor function is to add our own logic before and after the Bean object has been instantiated and dependency injection completed, before and after displaying the call to the initialization method. Note that it is triggered after the Bean instantiation and after the dependency injection has been completed. The source code for the interface is as follows

There are two methods in the source code:

postProcessBeforeInitialization: Instantiation, dependency injection complete, then invoke the task that completes the initialization of game rating before display initialization

postProcessAfterInitialization: instantiation, dependency injection, execution after initialization

Here's a little demo to try it out

Create a new class called myBeanPostProcessor, and we implement the interface for this postprocessor

Explanation of parameters:

Parameter 1 bean: that is the object we injected into ioc

Parameter 2 beanName: The name of the object we injected into ioc

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

  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println(beanName+"After Initialization Execution");
    return bean;
  }
}

Simple example, after implementation, we can see the output information before and after the initialization of the injected object

Bean Factory Post Processor

This bean factory processor is some modifications to beans before all beans are created. What can we do with beans before we construct objects?

PosProcessBeanFactory method: The parameter has an object with a bean factory, and you can see some information

He just returns an object that created the factory before bena was created, and we can see the bean information that will be created in the factory.

BeanDefinitionRegistryPostProcessor (Post bean Component Information Processor)

Postprocessor for handling some of our configuration when placing containers in spring, such as whether or not a singleton is present, initialization method, destruction method, etc.

Method

Configuration information registration for postProcessBeanDefinitionRegistrybean object

Post ProcessBeanFactory then enters the bean's factory

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry)
      throws BeansException {
    System.out.println("postProcessBeanDefinitionRegistry:" + beanDefinitionRegistry);
  }

  public void postProcessBeanFactory(
      ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    System.out.println("ConfigurableListableBeanFactory:" + configurableListableBeanFactory);
  }

Each life cycle of a Bean component

  • bean component information processor: component information registration
  • bean factories are created, and the rear factory processors we write ourselves are the same.
  • bean creation and injection complete
  • Before initialization
  • Initialization complete
  • After Initial
  • Destroy

Small demo, using the Bean Factory to manipulate the injection of beans

New configuration file: beanFactoryProcessor.xml, put two bean objects without any configuration

    <bean id="mypostProcessBeanFactory" class="com.hyc.Processor.MypostProcessBeanFactory"/>
    <bean id="demobean" class="com.hyc.springBean.demoBean"></bean>

Use beanFactory to manipulate bean objects, implement configuration, and property injection

public class MypostProcessBeanFactory implements BeanFactoryPostProcessor {
  public void postProcessBeanFactory(
      ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    System.out.println("configurableListableBeanFactory" + configurableListableBeanFactory);
    // Get Object
    AbstractBeanDefinition demobean =
        (AbstractBeanDefinition) configurableListableBeanFactory.getBeanDefinition("demobean");
    // Set Initialization Method
    demobean.setInitMethodName("init1");
    // Injection name value
    MutablePropertyValues propertyValues = demobean.getPropertyValues();
    propertyValues.add("name", "PostProcessorFactory bane name");
    // Set Destroy Method
    demobean.setDestroyMethodName("destroy1");
  }
}

Output view information after

Next let's copy a custom bean factory

Configuration file adds a new bean

    <bean id="mypostProcessBeanFactory2" class="com.hyc.Processor.MypostProcessBeanFactory2"/>

Implement priority interface for two factories, set priority,

Factory 1 has a priority of 5

No. 2 plant priority is 10

public class MypostProcessBeanFactory2 implements BeanFactoryPostProcessor, Ordered {
 //Code omission from previous factory

  public int getOrder() {
    return 10;
  }

Start test

You can see that level 5 is line executed

Perfect, and that's why using a post-processor to manipulate bean properties is real

spring Event Listener

You can listen to what happens in our spring, or you can customize an event listener for spring

The main thing to learn about this is what happens when spring executes in a container

Here we implement ApplicationListener<ApplicationEvent>

The objects in this generic are global messages, and we can also write our own custom

public class MyApplicationEvent extends ApplicationEvent {
  public MyApplicationEvent(Object source) {
    super(source);
  }

  String username;
  String emial;

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getEmial() {
    return emial;
  }

  public void setEmial(String emial) {
    this.emial = emial;
  }

  public MyApplicationEvent(Object source, String username, String emial) {
    super(source);
    this.username = username;
    this.emial = emial;
  }
}

Then create a new configuration file, Listener.xml, to add event listeners to the spring container

  <bean id="listener" class="com.hyc.listener.myApplicationListener"></bean>

Modify the event listener to see what happened when the bean s were generated

public class myApplicationListener implements ApplicationListener<ApplicationEvent> {
  public void onApplicationEvent(ApplicationEvent event) {
    System.out.println("Received Events" + event);
      //This fear of judgment is that if we have our own definition to turn event listeners into our own, we can guarantee that our own custom events will be output as well.
    if (event instanceof MyApplicationEvent) {
      MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
      System.out.println("User name" + myApplicationEvent.getUsername());
      System.out.println("email" + myApplicationEvent.getEmial());
    }
  }
}

After testing

public class listenerMain {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext ApplicationContext =
        new ClassPathXmlApplicationContext("Listener.xml");
    //Create Event Object
    MyApplicationEvent event = new MyApplicationEvent("Event Content", "james", "123@qq,com");
    //Send Events
    ApplicationContext.publishEvent(event);
    ApplicationContext.close();
    //
  }
}

You can see that the spring loading process in the diagram is becoming clearer and clearer

Explore Sources

Let's go into debugging to see the source code

Since there are so many sources, here's only a list of things that were done during execution

Factory Source

Loading process

New Object Locate spring Object, Locate Configuration File

Then judge refresh and start refreshing

refresh

What does refresh do with spring's core approach?

First, prepare to refresh:

  • Record milliseconds, turn off or not, choose start
  • Log printing, doing default things for subclasses, checking some attributes, whether there are some attributes of subclass replication, if there is, executing, not moving down
  • Judgement, then put some of the initialization events applied into the collection

When you are ready to refresh,

Prepare bean factory

  • Loader for adding bean s, parser for spring expressions, property editor
  • Set up some necessary post processors
  • Ignore some interfaces
  • Register information for bean s, join resource parsers, register event publishing, context objects
  • Get some system properties to determine the load, such as jre's name, user.home's path, locale, and so on
  • Then return to the factory object

Factory Object Creation

  • Determine if there is a factory, if not, create it
  • Create a default factory and return. The default factory contains a lot of default information
  • The bean factory is then assigned a value based on the conditions it satisfies
  • Parse description information class, load description information, if xml then parse xml
  • Copy the parsed class description i information to the Bean factory

The factory was created here

Post Processors

Register all the post processors, generally speaking. How many injected classes are how many post processors

Execute process

  • Traverse, how many post processors are there, create collections, loop to determine if all processors belong to the current interface, and then put all the post processors in the corresponding collections, giving the processor id
    • priority
    • Internal
    • Wait
  • After that, sort the processors in the priority set and register them in order
  • Then determine the set of other processors
  • Finalize the collection without priority and eventually register it all in the container

Internationalization and Event Listeners

  • Determine if internationalization exists, if included, join the factory, output log calls
  • Event listeners are also used to determine if there is an event listener. If a letter is taken out of it, the log is output, and if it is not, an event listener is created.

Register event listeners

  • The default is no, if any, get all default listeners
  • Set Temporary Class Loader
  • Determine if the event listener is empty, or if not bring it all out,

Create bean s

Create a singleton object, not lazily loaded

  • First find out if there is a value parser in the factory, and if not create a new one
  • View the frozen configuration, and for true convert the bean components that hold the reconfiguration file to an array of strings
  • Remove from the collection by name, iterate through the creation objects, get the bean information by name, meet three conditions before moving back
    • Cannot be abstract
    • Must be singleton
    • Can't be lazy
  • If not, it's factory creation
  • Get a single object from the cache, if you don't, check to see if the criteria are met, check to see if the object is created multiple times, and then check the bean factory.
  • Marks the current object, is being created, and then placed in the set collection, indicating the last creation.
  • Check the information of the current bean to see if additional dependencies are needed to create it, and determine if it is a singleton.
  • Store objects and a construction factory in a collection
  • There is an instance of resolveBeforeInstantiation created to create a proxy object through a post-processor. This step is likely to create the object, which is how we get the proxy object when we want to use aop.
  • If not, create the object, pass in the object information, judge again if it is singleton, and then create the singleton object.
  • Then judge whether the object needs to be specified. The default is empty parameter construction.
  • Then get the bean instance, decide if it is empty, judge the interface type, check the object, get the parameterless construction method
  • Create an object, mark the current construction method with reflection, and build an instance with a parameterless construction method, where the bean object is created successfully
  • Here the bean object is the initial state, wrapped in an initialization to BeanWapper, and an empty object is created here.
  • The postprocessor is then invoked, the postprocessor is invoked if there is one in the component, and the assignment of null objects starts here
  • Then get the single object again, then go get the assignment, and return to the created object
  • Create objects from a singleton factory and place the newly created objects in the singleton object collection
  • Remove the instance factory used to check for circular dependencies, confirm that the registered object is successful, set does not store duplicate values, so just one
  • Return object instance after a lot of judgment

Complete refresh, publish event message

  • Initialize the included processor, get in if there is one, and create if not
  • Refresh Post Processor After
  • Send create event information to tell spring that initialization is complete
  • Then the registration context gets the current name. If it's not empty, join the applicationContext and finish

Circular Dependency Problem

We create two objects,

UserA's constructor calls the UserB object

Circular dependency,

This is a debug breakpoint into a parametric construction method

  • Once in, you can see that you need parameters to refer to UserB, which is also a bean, so spring is going to create userB so userB needs parameters to create userA, which leads to a continuous cycle of creation
  • spring throws an exception when it finds that UserB is still creating userA. Why is it an exception when it is created again?
  • As we mentioned when we stored the beans we created before set up, as long as the beans were created, there was a judgment that SETIS no duplicate value and if it fails, it will prove that there was an object being created before... and an exception will be thrown
  • Resolve circular dependencies by caching bean s to create to determine if they are referenced repeatedly

How to solve it?

  • We use constructor calls to reference other classes, creating objects repeatedly
  • We just need to declare an application object with attributes, call it when needed, and destroy it when used
  • There will be no circular dependency

summary

The beauty of the spring framework is worth learning. This bean's life is just about explaining ideas and general processes. There are also many details that need to be combined with the scene. We need to explore them by ourselves, and continue to study deeply to make our technology powerful.

Posted by powelly on Sun, 10 Oct 2021 10:06:50 -0700