Spring-framework @Autowired注入bean 爲null之謎

環境:

JDK1.8java

Spring-framework4.1.2.RELEASEspring

以下圖所示的一個Spring javaSE工程app

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主類ui

輸出結果發現空指針異常,也就是說testInterface2的實現類並無注入進來spa

Exception in thread "main" java.lang.NullPointerException指針

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

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

 這是怎麼回事呢,是由於testInterfaceImpl2這個類沒有被Spring容器所管理嗎? xml

我打算輸出一下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的實例;

相關文章
相關標籤/搜索