В пакете Javax.ejb спецификации EJB 3.2 (JSR 345) определены аннотации @PrePassivate и @PostActivate. Они связаны с жизненным циклом EJB с сохранением состояния и могут произойти много раз во время существования EJB. Аннотации @PostConstruct и @PreDestroy являются частью спецификации CommonAnnotation 1.2 (JSR 250) и располагаются в пакете javax.annotation (как, например, @Resource или другие аннотации, связанные с безопасностью, которые вы увидите далее). Они связаны с жизненным циклом управляемых компонентов и срабатывают только один раз за время существования экземпляра класса (при его создании и разрушении).
Для методов обратного вызова применяются следующие правила.
• Метод не должен иметь никаких параметров и возвращает тип void.
• Метод не должен генерировать проверяемое исключение, но при этом может сгенерировать исключения времени выполнения. Генерация подобного исключения заставит откатить транзакцию, если таковая будет существовать (что описано в следующей главе).
• Метод может иметь типы доступа public, private, protected или быть доступным на уровне пакета, но при этом не должен иметь спецификаторов static или final.
• Метод может иметь несколько аннотаций (метод init(), который будет показан позже, в листинге 8.2, имеет аннотации @PostConstruct и @PostActivate). Однако может существовать только одна аннотация данного типа для каждого компонента (например, нельзя иметь два метода с аннотацией @PostConstruct для одного и того же сессионного компонента).
• Метод обратного вызова может получить доступ к данным среды окружения компонента (см. подраздел «Контекст именования среды» раздела «Внедрение зависимостей» главы 7).
Эти методы обратного вызова, как правило, используются для выделения и/или освобождения ресурсов компонента. В качестве примера в листинге 8.1 показан компонент CacheEJB типа «синглтон», использующий аннотацию @PostConstruct для инициализации кэша. Сразу после создания одного экземпляра компонента CacheEJB контейнер вызывает метод initCache().
@Singleton
public class CacheEJB {
··private Map
··@PostConstruct
··private void initCache() {
····cache.put(1L, "Первый товар в кэше");
····cache.put(2L, "Второй товар в кэше");
··}
··public Object getFromCache(Long id) {
····if (cache.containsKey(id))
······return cache.get(id);
····else
······returnnull;
····}
}
В листинге 8.2 показан фрагмент кода для компонента, сохраняющего свое состояние. Контейнер поддерживает диалоговое состояние, которое может включать в себя тяжелые ресурсы, такие как подключения к базе данных. Поскольку открывать соединение с базой данных довольно затратно по времени, одно соединение должно использоваться во всех вызовах и закрываться, когда компонент простаивает (или пассивизирован).
@Stateful
public class ShoppingCartEJB {
··@Resource(lookup = "java: comp/defaultDataSource")
··private DataSource ds;
··private Connection connection;
··private List
··@PostConstruct
··@PostActivate
··p rivate void init() {
····connection = ds.getConnection();
··}
··@PreDestroy
··@PrePassivate
··private void close() {
····connection.close();
··}
··//…
··@Remove
··public void checkout() {
····cartItems.clear();
··}
}