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.