Как я могу получить доступ к аннотированной переменной @Value из Конструктора? - PullRequest
2 голосов
/ 31 августа 2011

Я хочу создать компонент, который имеет значения из файла свойств.Я сделал что-то вроде этого:

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

Однако я не хочу инициировать вручную.Могу ли я инициировать это в конструкторе?Или любые другие альтернативы?

Ответы [ 3 ]

7 голосов
/ 31 августа 2011

Используйте @PostConstruct в вашем init() методе - он будет вызываться пружиной, как только объект окажется внутри контекста пружины, что означает все, если будут введены его зависимости.

2 голосов
/ 31 августа 2011

Подумайте об этом: чтобы весна добавила что-то в ваш бин, сначала нужно создать это, а не создавать, пока конструктор не завершит свою работу. Вы можете либо создать список лениво, либо реализовать интерфейс 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]));
    }
}
0 голосов
/ 31 августа 2011

В качестве обходного пути вы можете использовать фабричный шаблон, например:

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