问题描述
我有2个bean:A,BA里有字段用@Value注入,A还有个初始化方法;B里的初始化方法需要用到A的@Value字段和初始化方法的结果请问我该怎么配置才能让B正确初始化? 问题补充:只用@Resource和@PostConstruct的话,其实没什么问题的,关键是用到了@Value,@Value注入的时间似乎比@PostConstruct更迟@Servicepublic class SQLPropertiesLoader { @Value("#{sqlProperties['REPORT.UPDATE']}") private String reportUpdateSQL; public String getReportUpdateSQL(){ return reportUpdateSQL; }//等等}@Servicepublic class Job{@Resourceprivate SQLPropertiesLoader sqlProperties; @PostConstruct public init(){ String sql = sqlProperties.getReportUpdateSQL(); //等等 } @Async @Scheduled(fixedDelay = 10000L) public void job() //等等 }
解决方案
@Value注入的时间比@PostConstruct更早,我修改了一下范例。A.javaimport org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.ImportResource;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;@Component("a")@ImportResource("classpath:./properties-config.xml")public class A {@Resource(name = "aInject")private AInject aInject;@Value("#{testp[a_one]}")private String message;public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public AInject getaInject() {return aInject;}public void setaInject(AInject aInject) {this.aInject = aInject;}@PostConstructpublic void initA() {System.out.printf("A init do. [%s]n", this.getMessage());}}properties-config.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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" default-autowire="byName" default-lazy-init="true"><util:properties id="testp" location="classpath:./test.properties"/></beans>ABTest.javaimport org.junit.Before;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import scan.A;import scan.B;public class ABTest {private ApplicationContext ctx;private A a;private B b;@Beforepublic void init() {ctx = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/applicationContext-bean.xml"});b = ctx.getBean("b", B.class);a = ctx.getBean("a", A.class);}@Testpublic void testAB() {System.out.printf("Msg:%s@%s@%sn", a.getaInject().getInjectName(), b.getA().getaInject().getInjectName(),a.getMessage());a.getaInject().sayHello();}}test.propertiesa_one=Hello执行ABTest测试的结果:A init do. [Hello]B init do.Msg:A inject.@A inject.@HelloHello A inject.!注意看在@PostConstruct的方法中@Value已经注入成功!
解决方案二:
我假设你使用的Spring是2.5+版本,下面的例子对你应该有帮助:applicationContext-bean.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" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" default-autowire="byName" default-lazy-init="true"> <context:component-scan base-package="scan" /></beans>A.javapackage scan;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;@Component("a")public class A {@Resource(name = "aInject")private AInject aInject;public AInject getaInject() {return aInject;}public void setaInject(AInject aInject) {this.aInject = aInject;}@PostConstructpublic void initA() {System.out.println("A init do.");}}B.javapackage scan;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;/** * User: phoenixup * Date: 11-3-15 * Time: 下午12:29 * Desc: //TODO:WRITE YOUR OWN DESCRIPTION. */@Component("b")public class B {@Resource(name = "a")private A a;public A getA() {return a;}public void setA(A a) {this.a = a;}@PostConstructpublic void initB() {System.out.println("B init do.");}}AInject.javapackage scan;import org.springframework.stereotype.Service;@Service("aInject")public class AInject {private String injectName = "A inject.";public String getInjectName() {return injectName;}public void setInjectName(String injectName) {this.injectName = injectName;}/*other thing*/public void sayHello() {System.out.printf("Hello %s!n", injectName);}}ABTest.javaimport org.junit.Before;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import scan.A;import scan.B;public class ABTest {private ApplicationContext ctx;private A a;private B b;@Beforepublic void init() {ctx = new ClassPathXmlApplicationContext(new String[]{"/applicationContext-bean.xml"});b = ctx.getBean("b", B.class);a = ctx.getBean("a", A.class);}@Testpublic void testAB() {System.out.printf("Msg:%s@%sn", a.getaInject().getInjectName(), b.getA().getaInject().getInjectName());a.getaInject().sayHello();}}测试包使用的junit,运行ABtest测试,可以得到的结果:A init do.B init do.Msg:A inject.@A inject.Hello A inject.!注意消息的次序,应该可以满足你的要求。关于@Resource、@PostConstruct注解的方法可以查阅文档。如果你使用的spring版本不支持注解,修改applicationContext-bean.xml,在<bean/>元素中使用init-method属性也可以满足要求。