开发者

How can I access to @Value annotated variable from Constructor?

I want to make a bean which has values from properties file. I made something like this:

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

        //....
    }
}

But when I autowire like this @Autowired MainNavs 开发者_开发百科navs;, it makes NullPointerException because the names and ids were not initiated when it try to access those in constructor.

If I made some method like init() and tried to initiate with it, there wasn't any problem.

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

However, I don't want initiate manually. Can I initiate it in constructor? Or any other alternatives?


Use @PostConstruct on your init() method - it will be called by spring as soon as the object is inside the spring context, which means all if its dependencies will be injected.


Think about it: for spring to inject something into your bean, it needs to be created first, and it isn't created until the constructor has finished its job. You can either create the list lazily, or you can implement the spring interface InitializingBean. In your case

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]));
    }
}


As a work around you could use a factory pattern, something like:

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();
  }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜