A spring injection problem, first look at an ordinary spring Bean,
public class Foo {@AutowiredBar bar;public void dosomething () {bar.dosomething ();}}
Spring Configuration One:
<bean id= "Bar" class= "Com.test.Bar" ></bean><bean id= "foo" class= "Com.test.Foo" ></bean>
Unit tests:
@Testpublic void Test_dosomthing () {ApplicationContext ctx = new Classpathxmlapplicationcontext (" Applicationcontext-test.xml "); Foo foo = Ctx.getbean (Foo.class); foo.dosomething ();}
Execute the above test method, error
Java.lang.NullPointerExceptionat com.test.Foo.doSomething (foo.java:15) at com.test.FooTest.test_doSomthing ( FOOTEST.JAVA:13)
The bar in the Foo Bean is not injected.
Spring Configuration II:
<context:component-scan base-package= "Com.test" ></context:component-scan>
The above-mentioned unit test method can be successfully implemented when the configuration is changed to two. After analyzing the log and viewing the source code, it was found that 6 beans were loaded with configuration two o'clock, as follows:
DEBUG Org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions ( abstractbeandefinitionreader.java:216) Loaded 6 bean Definitions from location pattern [Applicationcontext-test.xml] DEBUG Org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory ( abstractapplicationcontext.java:530) Bean Factory for Org[email protected]3c4e80d3:org.s[email Protected]14cc51c8: defining Beans [Bar,foo,org.springframework.context.annotation.internalconfigurationannotationprocessor, Org.springframework.context.annotation.internalAutowiredAnnotationProcessor, Org.springframework.context.annotation.internalRequiredAnnotationProcessor, Org.springframework.context.annotation.internalCommonAnnotationProcessor]; Root of Factory hierarchy
Instead, use the configuration for only two beans at a moment, as follows:
DEBUG Org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions ( abstractbeandefinitionreader.java:216) Loaded 2 bean definitions from location pattern [Applicationcontext-test.xml] DEBUG Org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory ( abstractapplicationcontext.java:530) Bean Factory for Org[email protected]45ebbb93:org.s[email protected]18481697: defining beans [Bar,foo]; Root of Factory hierarchy
The reason for the configuration of the two execution unit tests seems to be the extra beans. Is it that as long as there are context:component-scan elements in the automatic there will be a few beans generated? Verify this hypothesis
Add a context:component-scan element that is not actually meaningful in configuration one, as follows:
<context:component-scan base-package= "Com.nonexist" ></context:component-scan>
At this point, the execution unit test can pass, same as configuration two will also load 6 beans. So which of the 6 beans actually played a role in injecting bar to Foo?
The breakpoint debugging found that the Autowiredannotationbeanpostprocessor Bean has played a role, see output log:
2015-04-25 20:23:09 debug org.springframework.beans.factory.annotation.injectionmetadata.< Init> (injectionmetadata.java:60) found injected element on class [ com.test.foo]: autowiredfieldelement for com.test.bar com.test.foo.bar2015-04-25 20:23:09 debug org.springframework.beans.factory.annotation.injectionmetadata.inject ( injectionmetadata.java:85) Processing injected method of bean ' foo ': Autowiredfieldelement for com.test.bar com.test.foo.bar2015-04-25 20:23:09 debug org.springframework.beans.factory.support.abstractbeanfactory.dogetbean (AbstractBeanFactory.java:245) Returning cached instance of singleton bean ' Bar ' 2015-04-25 20:23:09 debug Org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.registerDependentBeans ( Autowiredannotationbeanpostprocessor.java:424) Autowiring by type from bean name ' foo ' to bean named ' Bar ' 2015-04-25 20:23:09 debug Org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean ( abstractautowirecapablebeanfactory.java:458) finished creating instance of bean ' foo '
So directly in the configuration of an explicit add autowiredannotationbeanpostprocessor bean? As shown below:
<bean id= "Bar" class= "Com.tcl.account.service.test.Bar" ></bean><bean id= "foo" class= " Com.tcl.account.service.test.Foo "></bean><bean id=" Autowiredannotationbeanpostprocessor "class=" Org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "></bean>
Will the test pass? Will pass. See log:
Debug org.springframework.beans.factory.support.abstractbeandefinitionreader.loadbeandefinitions ( abstractbeandefinitionreader.java:216) Loaded 3 bean definitions from location pattern [applicationcontext-test.xml]debug Org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory ( abstractapplicationcontext.java:530) bean factory for org[email protected] 7767d3c1: org.s[email protected]1924ed52: defining beans [bar,foo, autowiredannotationbeanpostprocessor]; root of factory hierarchydebug Org.springframework.beans.factory.annotation.injectionmetadata.<init> (InjectionMetadata.java:60) found injected element on class [com.test.foo]: autowiredfieldelement for com.test.Bar com.test.Foo.barDEBUG Org.springframework.beans.factory.annotation.InjectionMetadata.inject (INJECtionmetadata.java:85) Processing injected method of bean ' foo ': autowiredfieldelement for com.test.bar com.test.foo.bardebug Org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean (abstractbeanfactory.java:245) Returning cached instance of singleton bean ' Bar ' debug Org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.registerDependentBeans ( autowiredannotationbeanpostprocessor.java:424) autowiring by type from bean name ' foo ' to bean named ' bar ' debug Org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean ( abstractautowirecapablebeanfactory.java:458) finished creating instance of bean ' foo '
So why does adding the Context:componet-scan element in the config file automatically add the other 4 beans? A breakpoint debug found that spring implicitly loaded 4 beans were loaded in the following way:
Set<beandefinitionholder> Org.springframework.context.annotation.AnnotationConfigUtils.registerAnnotationConfigProcessors ( Beandefinitionregistry registry, Object Source)
Its invocation chain is as follows:
Research on automatic injection failure in spring configuration file when directly defining beans