Spring-framework @Autowired注入bean 为null之谜


声明:本文转载自https://my.oschina.net/u/2338224/blog/1822135,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

环境:

JDK1.8

Spring-framework4.1.2.RELEASE

如下图所示的一个Spring javaSE工程

applicationContext.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>  <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:tx="http://www.springframework.org/schema/tx"        xmlns:aop="http://www.springframework.org/schema/aop"        xmlns:context="http://www.springframework.org/schema/context"        xmlns="http://www.springframework.org/schema/beans"        xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx.xsd        http://www.springframework.org/schema/aop        http://www.springframework.org/schema/aop/spring-aop.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context.xsd">   	   	<context:component-scan base-package="com.chenjun.learnspring.annotation" />   	 </beans>  

 

TestInterface2内容:

package com.chenjun.learnspring.annotation;  public interface TestInterface2 { 	public void print(); } 

TestInterfaceImpl2内容:

package com.chenjun.learnspring.annotation;  import org.springframework.stereotype.Service;  @Service public class TestInterfaceImpl2 implements TestInterface2 {  	public void print() { 		System.out.println("TestInterfaceImpl2 is print"); 	}  } 

App.java内容: 

package com.chenjun.learnspring.annotation;  import javax.annotation.Resource;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component;   @Component public class App { 	 	@Autowired 	private TestInterface2 testInterface2;  	public static void main(String[] args) { 		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 		App app = new App(); 		app.proxyPrint(); 	} 	 	public void proxyPrint() { 		testInterface2.print(); 	}  } 

编译运行App.class主类

输出结果发现空指针异常,也就是说testInterface2的实现类并没有注入进来

Exception in thread "main" java.lang.NullPointerException

    at com.chenjun.learnspring.annotation.App.proxyPrint(App.java:24)

    at com.chenjun.learnspring.annotation.App.main(App.java:20)

 这是怎么回事呢,是因为testInterfaceImpl2这个类没有被Spring容器所管理吗? 

我打算输出一下Spring容器里面的bean一看究竟:

于是我编写如下代码:

略微修改之后的App.java

package com.chenjun.learnspring.annotation;  import javax.annotation.Resource;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component;   @Component public class App { 	 	@Autowired 	private TestInterface2 testInterface2;  	public static void main(String[] args) { 		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 		 		String[] beanArray = applicationContext.getBeanDefinitionNames(); 		 		for(String s : beanArray) { 			System.out.println(s); 		} 		App app = new App(); 		 		app.proxyPrint(); 	} 	 	public void proxyPrint() { 		testInterface2.print(); 	}  } 

我把Spring容器里面现在的bean名称都打印一下,如下:

testInterfaceImpl2 app org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor Exception in thread "main" java.lang.NullPointerException 	at com.chenjun.learnspring.annotation.App.proxyPrint(App.java:31) 	at com.chenjun.learnspring.annotation.App.main(App.java:27) 

从上面控制台输出信息可以看到,spring容器中确实已经有了testInterfaceImpl2,但是为什么上面声明这个bean的时候他没有注入呢?

原因就在于这行

App app = new App();

这行代码把App用new关键字进行创建对象,这就使得app依赖的其他bean已经脱离了spring的依赖注入管理

找到原因之后,最终我修改App.java的代码如下:

正确的注入方式

package com.chenjun.learnspring.annotation;  import javax.annotation.Resource;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component;   @Component public class App { 	 	@Autowired 	private TestInterface2 testInterface2;  	public static void main(String[] args) { 		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 		App app = applicationContext.getBean(com.chenjun.learnspring.annotation.App.class); 		app.proxyPrint(); 	} 	 	public void proxyPrint() { 		testInterface2.print(); 	}  } 

 输出结果:

总结:

输出正常. 这也就说明了,spring在管理bean注入的策略是这样的:

当A组件依赖B, 要想使用spring依赖注入得到组件B的实例, 那么A本身也要是通过Spring的bean来创建的才行. 而不是直接new出A的实例;

 

本文发表于2018年06月01日 08:00
(c)注:本文转载自https://my.oschina.net/u/2338224/blog/1822135,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1971 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1