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因为当它尝试访问构造函数中的那些时并没有启动names和。ids

如果我做了一些类似的方法init()并尝试使用它来启动,那么没有任何问题。

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

但是,我不想手动启动。我可以在构造函数中启动它吗?还是有其他选择?

4

3 回答 3

9

@PostConstruct在你的方法上使用init()- 只要对象在 spring 上下文中,它就会被 spring 调用,这意味着如果它的依赖项将被注入。

于 2011-08-31T06:35:00.653 回答
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]));
    }
}
于 2011-08-31T06:43:42.603 回答
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();
  }
}
于 2011-08-31T06:35:26.120 回答