如何从Constructor访问@Value注释变量?

时间:2011-08-31 05:02:26

标签: java spring spring-mvc annotations spring-3

我想创建一个包含属性文件值的bean。我做了这样的事情:

@Component
public class MainNavs implements Iterable<Nav>{
    @Value("${newshome.navs.names}")
    String[] names;

    @Value("${newshome.navs.ids}")
    String[] ids;

    final private List<Nav> navs = new ArrayList<Nav>();

    public MainNavs() throws Exception {            
        for (int i = 0; i < names.length; i++) {
            navs.add(new Nav(names[i], ids[i]));
        }
    }

    public Iterator<Nav> iterator() {
        Iterator<Nav> n = navs.iterator();
        return n;
    }

    public class Nav {      
        private String name;
        private String id;
        private String imageNumber;

        public Nav(String name, String id, String imageNumber) {
            this.name = name;
            this.id = id;
        }

        //....
    }
}

但是,当我像@Autowired MainNavs navs;一样自动发送时,它会生成NullPointerException,因为namesids在尝试访问构造函数时未启动。

如果我制作了一些类似init()的方法,并尝试使用它,则没有任何问题。

public init() throws Exception {            
    for (int i = 0; i < names.length; i++) {
        navs.add(new Nav(names[i], ids[i]));
    }
}

但是,我不想手动启动。我可以在构造函数中启动它吗?还是其他任何替代方案?

3 个答案:

答案 0 :(得分:7)

@PostConstruct方法上使用init() - 一旦对象在spring上下文中,它就会被spring调用,这意味着所有它都会被注入。

答案 1 :(得分:2)

考虑一下:对于spring向bean中注入一些东西,需要首先创建它,并且在构造函数完成其工作之前不会创建它。您可以懒惰地创建列表,也可以实现spring接口InitializingBean。在你的情况下

public class MainNavs implements Iterable<Nav>, InitializingBean {
...
public void afterPropertiesSet() throws Exception {            
    for (int i = 0; i < names.length; i++) {
        navs.add(new Nav(names[i], ids[i]));
    }
}

答案 2 :(得分:0)

作为一种解决方法,您可以使用工厂模式,例如:

public class MainNavs implements Iterable<Nav>{

  // ...

  public init() throws Exception {            
      for (int i = 0; i < names.length; i++) {
          navs.add(new Nav(names[i], ids[i]));
      }
  }

  public static MainNavs createInstance() throws Exception {
    MainNavs result = new MainNavs();
    return result.init();
  }
}