我有2个bean:A,B
A里有字段用@Value注入,A还有个初始化方法;
B里的初始化方法需要用到A的@Value字段和初始化方法的结果
请问我该怎么配置才能让B正确初始化?
@Value注入的时间比@PostConstruct[b]更早[/b],我修改了一下范例。
[b]A.java[/b]
[code="java"]
import 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;
}
@PostConstruct
public void initA() {
System.out.printf("A init do. [%s]\n", this.getMessage());
}
}[/code]
[b]properties-config.xml[/b]
[code="xml"]<?xml version="1.0" encoding="UTF-8"?>
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"/>
[/code]
[b]ABTest.java[/b]
[code="java"]import 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;
@Before
public 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);
}
@Test
public void testAB() {
System.out.printf("Msg:%s@%s@%s\n", a.getaInject().getInjectName(), b.getA().getaInject().getInjectName(),a.getMessage());
a.getaInject().sayHello();
}
}[/code]
test.properties
[code="txt"]a_one=Hello[/code]
执行ABTest测试的结果:
A init do.[b] [Hello][/b]
B init do.
Msg:A inject.@A inject.@Hello
Hello A inject.!
[b]注意看在@PostConstruct的方法中@Value已经注入成功![/b]
我假设你使用的Spring是2.5+版本,下面的例子对你应该有帮助:
[b]applicationContext-bean.xml[/b]
[code="xml"]<?xml version="1.0" encoding="UTF-8"?>
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">
[/code]
[b]A.java[/b]
[code="java"]package 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;
}
@PostConstruct
public void initA() {
System.out.println("A init do.");
}
}[/code]
[b]B.java[/b]
[code="java"]package scan;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
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;
}
@PostConstruct
public void initB() {
System.out.println("B init do.");
}
}
[/code]
[b]AInject.java[/b]
[code="java"]package 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);
}
}[/code]
[b]ABTest.java[/b]
[code="java"]import 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;
@Before
public void init() {
ctx = new ClassPathXmlApplicationContext(
new String[]{"/applicationContext-bean.xml"});
b = ctx.getBean("b", B.class);
a = ctx.getBean("a", A.class);
}
@Test
public void testAB() {
System.out.printf("Msg:%s@%s\n", a.getaInject().getInjectName(), b.getA().getaInject().getInjectName());
a.getaInject().sayHello();
}
}[/code]
测试包使用的junit,运行ABtest测试,可以得到的结果:
A init do.
B init do.
Msg:A inject.@A inject.
Hello A inject.!
注意消息的次序,应该可以满足你的要求。
关于@Resource、@PostConstruct注解的方法可以查阅文档。
如果你使用的spring版本不支持注解,修改applicationContext-bean.xml,在元素中使用init-method属性也可以满足要求。