spring bean 初始化问题

我有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;

/**

  • 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;
    }

    @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属性也可以满足要求。