配置文件参数注入|Spring配置文件中如何注入另一个XML中的配

|

㈠ Spring配置文件中如何注入另一个XML中的配

主要有两种方式:1、在一个配置文件中使用import标签导入其他配置文件,即applicationContext.xml中部分代码如下:<import resource="applicationContext-.xml" /><import resource="applicationContext-service.xml" /><import resource="applicationContext-action.xml" />2、在web.xml中配置Spring配置文件处导入多个配置文件,即可a、导入多个配置文件web.xml部分代码如下:<context-param> <param-name>contextConfigLocation</param-name> <param-value> applicationContext-core.xml, applicationContext-.xml, applicationContext-service.xml, applicationContext-action.xml </param-value></context-param>b、使用*通配符导入多个配置文件web.xml部分代码如下:<context-param> <param-name>contextConfigLocation</param-name> <param-value> applicationContext-*.xml </param-value></context-param>

㈡ spring 配置文件的bean自动注入失败的解决方法是什么

一个Spring注入问题,首先看一个普通Spring Bean,

publicclassFoo{@AutowiredBarbar;publicvoiddoSomething(){bar.doSomething();}}

Spring配置一:

<beanid="bar"class="com.test.Bar"></bean><beanid="foo"class="com.test.Foo"></bean>

单元测试:

@Testpublicvoidtest_doSomthing(){ApplicationContextctx=("applicationContext-test.xml");Foofoo=ctx.getBean(Foo.class);foo.doSomething();}

执行上述测试方法,报错

java.lang.NullPointerExceptionatcom.test.Foo.doSomething(Foo.java:15)atcom.test.FooTest.test_doSomthing(FooTest.java:13)

即foo bean中的bar并未注入。

Spring配置二:

<context:component-scanbase-package="com.test"></context:component-scan>

当改成配置二后执行上述单元测试方法便能成功通过。经分析日志及查看源代码,发现使用配置二时供装载了6个bean,如下所示:

DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[applicationContext-test.xml]DEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.@3c4e80d3:org.springframework.beans.factory.support.DefaultListableBeanFactory@14cc51c8:definingbeans[bar,foo,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.];rootoffactoryhierarchy

而使用配置一时只有两个bean,如下所示:

DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[applicationContext-test.xml]DEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.@45ebbb93:org.springframework.beans.factory.support.DefaultListableBeanFactory@18481697:definingbeans[bar,foo];rootoffactoryhierarchy

配置二执行单元测试通过的原因似乎就在于多出的这几个bean。是不是只要有context:component-scan元素在自动就会有这几个bean的产生?验证此假设

在配置一中添加一个无实际意义的context:component-scan元素,如下所示:

<context:component-scanbase-package="com.nonexist"></context:component-scan>

这时执行单元测试能通过,同配置二一样也会装载6个bean。那么这6个bean中到底哪个对注入bar到Foo中起了作用呢?

经过断点调试发现是 bean起了作用,见输出日志:

2015-04-2520:23:09DEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.<init>(InjectionMetadata.java:60)Foundinjectedelementonclass[com.test.Foo]:AutowiredFieldElementforcom.test.Barcom.test.Foo.bar2015-04-2520:23:09DEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:85)'foo':AutowiredFieldElementforcom.test.Barcom.test.Foo.bar2015-04-2520:23:09DEBUGorg.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:245)'bar'2015-04-2520:23:09DEBUGorg.springframework.beans.factory.annotation..registerDependentBeans(.java:424)Autowiringbytypefrombeanname'foo'tobeannamed'bar'2015-04-2520:23:09DEBUGorg.springframework.beans.factory.support..createBean(.java:458)'foo'

那么直接在配置一种显式添加bean呢?如下所示:

<beanid="bar"class="com.tcl.account.service.test.Bar"></bean><beanid="foo"class="com.tcl.account.service.test.Foo"></bean><beanid=""class="org.springframework.beans.factory.annotation."></bean>

测试会不会通过?会通过。见日志:

DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[applicationContext-test.xml]DEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.@7767d3c1:org.springframework.beans.factory.support.DefaultListableBeanFactory@1924ed52:definingbeans[bar,foo,];rootoffactoryhierarchyDEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.<init>(InjectionMetadata.java:60)Foundinjectedelementonclass[com.test.Foo]:AutowiredFieldElementforcom.test.Barcom.test.Foo.barDEBUGorg.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:85)'foo':AutowiredFieldElementforcom.test.Barcom.test.Foo.barDEBUGorg.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:245)'bar'DEBUGorg.springframework.beans.factory.annotation..registerDependentBeans(.java:424)Autowiringbytypefrombeanname'foo'tobeannamed'bar'DEBUGorg.springframework.beans.factory.support..createBean(.java:458)'foo'

那么为什么在配置文件中添加了context:componet-scan元素后就会自动添加那另外4个bean呢?经过断点调试发现Spring隐式装载的4个bean是在如下方法中加载的:

Set<BeanDefinitionHolder>org.springframework.context.annotation.AnnotationConfigUtils.(,Objectsource)

其调用链如下所示:

补充一:

若仍用配置一,但单元测试改成如下形式也可以测试通过。

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:/applicationContext-test.xml"})publicclassFooTest2{@AutowiredprivateFoofoo;@Testpublicvoidtest_doSomthing(){foo.doSomething();}}

当然一点都不意外,这种方式也会隐式加载那4个bean,见日志:

DEBUGorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:216)[classpath:/applicationContext-test.xml]INFOorg.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:500)Refreshingorg.springframework.context.support.GenericApplicationContext@51f3336e:startupdate[SunApr2617:27:35CST2015];rootofcontexthierarchyDEBUGorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:530)Beanfactoryfororg.springframework.context.support.GenericApplicationContext@51f3336e:org.springframework.beans.factory.support.DefaultListableBeanFactory@4f9d1352:definingbeans[bar,foo,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.,org.springframework.context.annotation.];rootoffactoryhierarchy

补充二,若使用的是@Value,效果同@Autowired,即也需要隐式加载 bean。

publicclassFoo{@Value("${bar}")Stringbar;publicvoiddoSomething(){System.out.println(bar);}}

补充三:

若使用配置一,@PostConstruct标注的方法也不会被执行,但此时需要隐式加载的Spring bean是:org.springframework.context.annotation.

补充四:

在配置一中添加如下配置

<context:annotation-config/>

也会隐式加载那4个bean

㈢ 怎么创建junit4 注入spring 配置文件

1 建立一个test的目录,在此目录下放置所有的JunitTestCase类和TestCase的配置文件2 将项目中的Spring配置文件(默认名称为applicationContext.xml)复制到test目录下,并重新命名为JunitTestConf.xml。3 根据Junit测试的需要修改JunitTestConf.xml文件中的内容,如数据库连接等。4 新建一个名为SpringConfForTest.java的类,在此类中配置Spring启动所需的配置文件,并启动Spring。此类的内容如下:package test;import org.junit.AfterClass;import org.junit.BeforeClass;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.;import com.soma.global.WebContextHolder;public class SpringConfForTest { @BeforeClass public static void setUpBeforeClass() throws Exception { //Spring启动所需要的配置参数文件,其中test/JunitTestConf.xml文件中保存了数据库连接等参数,可根据具体情况做修改 String[] paths = new String[] {"test/JunitTestConf.xml", "com/soma/conf/applicationContext–hr.xml","com/soma/conf/applicationContext-.xml","com/soma/conf/applicationContext–bug.xml","com/soma/conf/applicationContext–change.xml","com/soma/conf/applicationContext–common.xml","com/soma/conf/applicationContext-service-hr.xml" }; //启动Spring,得到Spring环境上下文 ApplicationContext ctx = new (paths); //在此类启动时,将Spring环境上下文保存到单根类WebContextHolder中,以提供给其它的测试类使用 WebContextHolder.getInstence().setApplicationContext(ctx); } @AfterClass public static void tearDownAfterClass() throws Exception { } @Test public void test(){ //必须要写一个test空方法,否则SpringConfForTest类不会启动 }} 5 新建TestSuite类,类名为AllTests,类的内容如下所示:package test;import junit.framework.Test;import junit.framework.TestSuite;import org.junit.runner.RunWith;import org.junit.runners.Suite;import test.com.soma.domain.busilogic.hr.HrBusiLogicTest;import test.com.soma.domain.service.hr.checkOverTimeDateTest;@RunWith(Suite.class)@Suite.SuiteClasses({ SpringConfForTest.class, HrBusiLogicTest.class, checkOverTimeDateTest.class})/** * 批量执行Junit测试类,把类名写入到上面的Suite.SuiteClasses({})中,用逗号分隔 */public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("Test for test"); //$JUnit-BEGIN$ //$JUnit-END$ return suite; }}注意:将SpringConfForTest.class放在第一个执行,以启动Spring配置环境,把自己的TestCase类放到后面,用逗号分开。在测试时,只要执行这个TestSuite类就可以了。6 写自己的TestCase类,以CheckOverTimeDateTest.java为例子,文件内容如下:public class CheckOverTimeDateTest { private static HrTbovertimeManager hrTbovertimeManager; private static ExcuteSqlDAO excuteSqlDAO; @BeforeClass public static void setUpBeforeClass() throws Exception { //从Spring上下文中得到hrTbovertimeManager接口类的实例 hrTbovertimeManager=(HrTbovertimeManager)BeanUtil.getBean("hrTbovertimeManager");excuteSqlDAO = (ExcuteSqlDAO) BeanUtil.getBean("excuteSqlDAO"); } @Test public void testGetProjectList()throws Exception { List<OvertimeDetailValue> overtimeDetailValueList = new ArrayList<OvertimeDetailValue>(); int index = 9; for(int i = 1 ;i <= index;i++){ OvertimeDetailValue overtimeDetailValue = new OvertimeDetailValue(); overtimeDetailValue.setOtApplyDate("2009-05-0"+i); overtimeDetailValueList.add(overtimeDetailValue); } String resultStr = hrTbovertimeManager.checkOverTimeDate(overtimeDetailValueList); assertEquals("false", resultStr); }/** * 导入2009-03月份出勤记录excel文件,返回null表示导入成功,需要先删除3月份的数据 */ @Test public void testSaveExcelDutyInformation() throws Exception{ // 在导入3月份出勤记录前先删除3月份的记录,执行delete from hr_tbtyinformation; excuteSqlDAO.excuteSql("delete from hr_tbtyinformation where tydate>='2009-02-26' and tydate<='2009-03-25'"); // System.out.println("———-"+System.getProperty("user.dir")+"/src/test/ty200903.xls"); String fileName = System.getProperty("user.dir") + "/src/test/ty200903.xls"; assertNull(hrTbtyInformationManager.saveExcelDutyInformation(fileName)); }}说明:BeanUtil.getBean("")相当于WebContextHolder.getInstence().getApplicationContext().getBean(""),只是对此方法做了封装。7 在Eclipse中,启动AllTests,选择“Run As JunitTest”,即可先启动Spring环境,再依次运行你自己所写的JunitTestCase,是不是很简单哪?赶快动手试试吧。


赞 (0)