Sping之自动注入-1

最近终于能静下心来、一步步的学习Java Web开发。在学习的过程中,遇到太多的问题。一开始好些问题真是不知道怎么解决。在这里要非常感谢《Sping In Action》一书的作者,感谢他能写出此书,让我受益匪浅,您辛苦了!吐舌头奋斗


本着“相互学习、共同进步”的原则,从今天开始,决定把自己遇到的问题,以及解决的方法都分享给大家。好以就不废话了,开始今天的分享。


今天在学习Spring以注解方式注入时,报以下错误:

th03::MianRun::run()
一月 21, 2016 11:16:01 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@790f3a9c: startup date [Thu Jan 21 23:16:01 CST 2016]; root of context hierarchy
一月 21, 2016 11:16:01 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [th03/spring.xml]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testcls1': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: th03.TestCls2 th03.TestCls1.m_cls2; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [th03.TestCls2] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at th03.MainRun.run(MainRun.java:19)
    at kpy.SpringInAction.App.th_run(App.java:22)
    at kpy.SpringInAction.App.main(App.java:18)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: th03.TestCls2 th03.TestCls1.m_cls2; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [th03.TestCls2] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    ... 15 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [th03.TestCls2] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1100)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
    ... 17 more

我的代码如下:

//TestCls2.java
package th03;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Component
public class TestCls2 {
	
	void func1 () {
		System.out.println("TestCls2::func1 ()");
	}

}
TestCls1.java

package th03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Component
public class TestCls1 {
	
	@Autowired
	TestCls2 m_cls2;
	
	void func1 () {
		System.out.println("TestCls1::func1 ()");
		
		m_cls2.func1();
	}
}

主函数为

package th03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import kpy.SpringInAction.Th00;

public class MainRun implements Th00{
	
	@Autowired
	TestCls1 m_cls;
	
	public void run () {

		System.out.println("th03::MianRun::run()");
		
		ApplicationContext context = new ClassPathXmlApplicationContext("/th03/spring.xml");
		
		this.m_cls  = (TestCls1)context.getBean("testcls1");
		this.m_cls.func1();
	}
}

spring.xml文件内容为
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd"
    >

	<!-- 
	<context:annotation-config />
	 -->
	
	<!-- 定义自动注入功能搜索主包名 -->
	<!-- 以下这样配置要报错 
         <context:component-scan base-package="th03.*" />
	 -->
	 <context:component-scan base-package="th03" />
	
	<!--  -->
	<bean id="testcls1" class="th03.TestCls1" />

</beans> 

错误其实就是spring.xml中红色标记的那一句。在一个项目中,这样的配置,th03.*表示th03包以及子包。但不晓得这里为什么不行(这个问题先记着吧,后续再解决吐舌头


另外在MainRun中,已经对TestCls1标记为自动注入了,为什么还要以下这一句。

this.m_cls  = (TestCls1)context.getBean("testcls1");
个人解理是,由于在实现化MainRun这个类的实例时,还没有加载spring.xml,所以Java虚拟机并不知道怎么去实例化,因此用null去注入的(可以在类构造中进行new,再检查成员是否为null)。所以才在加载XML后,加了这一句。

另外,经测试,把这一句换成

this.m_cls = new TestCls1();

也是不行的。经@Autowired标注后的对象,已经注解包装后的类型,不能用原始类型(这里的TestCls1)去赋值。这纯属个人对于C++方面的知识的猜想,后续看了@autowired源码就能确认了吧。


注意:

自动注入功能,需要经spring配置文件中添加

xmlns:context="http://www.springframework.org/schema/context"

这个,不然后抛出以下异常

Caused by: org.xml.sax.SAXParseException; lineNumber: 23; columnNumber: 49; 元素 "context:component-scan" 的前缀 "context" 未绑定。


猜你喜欢

转载自blog.csdn.net/lijing_lj928/article/details/50558142
今日推荐