Problem description
?? When we use the Spring Framework for project development, the Autosire mechanism in spring is often used in order to configure the bean, and autowire can be divided into ==byname== and ==bytype== depending on the injection rules ( The use and difference of the two can be referred to [email protected] official documents. But have you ever thought about this when using the ==byname== mechanism in Autowire, when we configured two bean,spring with the same name attribute, what do I do when I inject it automatically? Will overwrite? or throw an exception? Or is it the other way?
Instance validation
?? To get the answer to the above question, the simplest solution is to validate the realism column-we first configure two beans with the same name in spring, with the following configuration information:
<bean name="Test1"class= "Com.yanxiao.Test1" > span class= "xml" ><property name= "age" value= "/>" </bean><bean name= "test1" Span class= "Hljs-class" >class= "Com.yanxiao.Test1" > <property name= "age" value= "/>BEAN>
?? The next time the program loads the configuration file, it will find that spring can start normally, so our previous assumptions about throwing exceptions are wrong. In the program to obtain the automatic injection of the name of the Bean object Test1 print its Age property, the result of the output is 21, indicating that = = for the same name of the beanspring will take an overriding policy, the subsequent configuration of the bean will overwrite the previously configured Bean object. ==
?? See here our initial question has been answered, but this question is not worth us to continue to think about it? Is it really reasonable that spring is such a mandatory overlay, and in some cases the errors caused by direct coverage can make it difficult for developers to troubleshoot errors in situations where the developer's negligence leads to the creation of the same name phenomenon?
So how do you solve this problem? By the self-discipline of developers? A bean that does not define a duplicate name? I think this is very unreliable, because project dependencies can be complex and developers are not the same. So I think it's only possible to solve this problem by introducing an error mechanism into the program.
?? Since spring as a good open source framework, its internal apart from covering the provision of other such as error mechanism and other options for us to choose?
SOURCE Analysis
?? With the above questions, we step through the verification process, from the source point of view of how the internal processing mechanism of spring.
?? When we track the bean registration phase and execute the method of the Defaultlistablebeanfactory class, we registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
find that there is a ==allowbeandefinitionoverriding== attribute.
Synchronized (This.beandefinitionmap) {Object oldbeandefinition =This.beandefinitionmap.Get (Beanname);if (oldbeandefinition! =NULL) {if (!this.allowbeandefinitionoverriding) {ThrowNew Beandefinitionstoreexception (Beandefinition.getresourcedescription (), Beanname,"Cannot register bean definition [" + beandefinition + "] for Bean '" + beanname + "': there is already [" + Oldbeandefinitio n + "] bound."); } else {if ( This.logger.isInfoEnabled ()) {this.logger.info ( "overriding Bean definition for bean ' "+ beanname + " ': replacing ["+ Oldbeandefinition + "] with ["+ Beandefinition + else {this.beandefinitionnames. Add (Beanname); this.frozenbeandefinitionnames = null;} this.beandefinitionmap.put (Beanname, beandefinition); }
Observing the logic of this piece of code we can see that the spring framework automatically injected when encountering the same name of the bean actually provides different options for us to choose, one is we have previously verified the coverage measures, through the view source we found: actually = = With coverage scenarios, if we have log printing support in our project, spring also provides log information at the info level. = = Another is the way to throw an exception.
Project Practice
?? Through the source code above, we know that the Spring framework provides a way for developers to successfully start a container's auto-injection process after they have solved the problem of ID or name duplication, which is useful in some cases where the project is highly reliable. So how to choose the processing mechanism of the same name throwing exception?
?? The key to the problem is how we should change the value of the Allowbeandefinitionoverriding property, and look at the document to see two scenarios for your reference:
Programme I
1, write an inheritance Contextloaderlistener listener, such as Springcontextloaderlistener, and then rewrite the method Customizecontext, such as
Publicclass springcontextloaderlistener extends contextloaderlistener {@ Override protected void Customizecontext (servletcontext ServletContext, configurablewebapplicationcontext applicationcontext) {super.customizecontext (ServletContext, ApplicationContext); xmlwebapplicationcontext context = (xmlwebapplicationcontext) ApplicationContext; Context.setallowbeandefinitionoverriding (false); //here Xmlwebapplicationcontext property Allowbeandefinitionoverriding is set to False, the value of this property finally //passed to allowbeandefinitionoverriding property of Defaultlistablebeanfactory class}}
2. Use the custom listener in Web. XML, configured as follows:
<listener> <listener-class>com.zyr.web.spring.SpringContextLoaderListener</listener-class></listener>
?? This way, when the project starts, if there is a bean with the same name or name in the different configuration files, throw the exception directly, and the container stops starting to reach our expected effect.
?? In fact, our goal is simply to change the value of a property, the solution to write a listener of their own method is still a bit troublesome. Here's a more straightforward scenario.
Programme II
1, create a implementation interface Applicationcontextinitializer class, such as Springapplicationcontextinitializer, the code is as follows:
public class SpringApplicationContextInitializer implements ApplicationContextInitializer<XmlWebApplicationContext> { public void initialize(XmlWebApplicationContext applicationContext) { applicationContext.setAllowBeanDefinitionOverriding(false);//在这里将XmlWebApplicationContext属性allowBeanDefinitionOverriding设置为false,这个属 //性的值最终会传递给DefaultListableBeanFactory类的allowBeanDefinitionOverriding属性 }}
2. Add a configuration to the Web. xml file
<context-param> <param-name>contextInitializerClasses</param-name> <param-value>com.zyr.web.spring.SpringApplicationContextInitializer</param-value> </context-param>
-
Top
-
0
-
Step
-
0
The spring framework uses byname to automatically inject the same name problem anatomy