2013-02-28 2 views
10

Я пытаюсь ввести объект-регистратор в класс, который реализован после одноэлементного подхода.Использование CDI в одноэлементном шаблоне

код выглядит почти так:

Logger класс:

public class LoggerFactory { 
    @Produces 
    public Logger getLogger(InjectionPoint caller){ 
     return Logger.getLogger(caller.getMember().getDeclaringClass().getName()); 
    } 
} 

Затем я создаю класс, который нуждается в логгер и реализующий Singleton Pattern:

public class MySingleton{ 
    @Inject 
    private Logger logger; 

    private MySingleton instance; 

    /* 
    * Private constructor for singleton implementation 
    */ 
    private MySingleton(){ 
     logger.info("Creating one and only one instance here!"); 
    } 

    public MySingleton getInstance(){ 

     if(instance == null) { 
      instance = new MySingleton(); 
     } 

     return instance; 
    } 

}

Если я запустил код (на Glassfish 3.1.2.2), я получаю NPE как только я попытаюсь использовать регистратор. Что я делаю неправильно (beans.xml файл на месте)? Я также попытался использовать @Inject с методом setter для объекта Logger, но не повезло.

+6

Инъекции происходят после конструкции. Таким образом, вы не можете использовать его в конструкторе. –

+1

Почему вы используете синглтон вместо инъекции, если вам это нужно, и пусть CDI делает его однобортным компонентом? –

+0

Я не знаю много о CDI, но разве вы не должны использовать ваш инжектор для создания своего объекта? С Spring инъекция выполняется только при создании объекта с использованием контекста приложения и с помощью Guice только при использовании инжектора. –

ответ

17

Инъекции происходят после конструкции. Поэтому вы не можете использовать его в конструкторе.

Одним из способов является добавление метода аннотированного @PostConstruct, который может быть вызван после инъекций.

@PostConstruct 
public void init() { 
    logger.info("Creating one and only one instance here!"); 
} 

На боковой стенке i Думайте, что вы ошибаетесь в проблеме. CDI имеет хорошую поддержку одноплодной

создать класс аннотированный @Singleton

@Singleton 
public class MySingleton { 

    @Inject 
    Logger logger; 

    @PostConstruct 
    public void init() { 
     logger.info("Creating one and only one instance here!"); 
    } 

} 

Выше предполагается, что вы используете для CDI Java EE (JSR-299).

Если вы используете JSR 330 Dependency Injection (Guice и т.д.) link

Вы можете использовать инъекции конструктора:

@Singleton 
public class MySingleton { 


    private final Logger logger; 

    @Inject 
    public MySingleton (Logger logger) { 
     this.logger = logger; 
     logger.info("Creating one and only one instance here!"); 
    } 
} 
+1

Большое спасибо за ответ @AkselWillgert, я пошел на реализацию CDI. – fabpicca

+1

Вы говорите javax.inject.Singleton или javax.ejb.Singleton здесь? JN01

4

Это не будет работать, так как инъекции, как уже упоминалось, будет выполняться после вызова конструктора.

Методы, аннотированные @PostConstruct, вызываются после завершения инъекции и перед тем, как сам объект будет поставляться в другом месте.

Однако инъекция работает только в том случае, если экземпляр вашего класса обеспечивается самой инъекцией. Это происходит из-за инъекции в зависимости от проксирования.

Поэтому вам нужно будет вводить свой MySingleton везде, где вам это нужно. Чтобы быть уверенным, что это синглтон, отметьте его @Singleton, и контейнер будет работать для вас.

Addiotnally остерегайтесь, что синглтон с точки зрения КДИ спецификации не означает, что только один экземпляров, а только один initialiation из @PostConstruct.

Смежные вопросы