Инъекция бобов внутри JPA @Entity
31613 просмотра
3 ответа
Можно ли внедрить bean-компоненты в JPA, @Entity
используя инъекцию зависимостей Spring?
Я попытался @Autowire ServletContext, но, хотя сервер действительно запустился, я получил исключение NullPointerException при попытке получить доступ к свойству компонента.
@Autowired
@Transient
ServletContext servletContext;
Автор: theblang
Источник
Размещён: 12.11.2019 09:22
Ответы (3)
39 плюса
Вы можете внедрить зависимости в объекты, не управляемые контейнером Spring, используя, @Configurable
как описано здесь: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-atconfigurable ,
Как вы уже поняли, если только не используется @Configurable
соответствующая ткацкая конфигурация AspectJ, Spring не внедряет зависимости в объекты, созданные с помощью new
оператора. На самом деле, он не вводит зависимости в объекты, если вы не получили их из ApplicationContext
, по той простой причине, что он просто не знает об их существовании. Даже если вы аннотируете свою сущность @Component
, создание этой сущности все равно будет выполняться new
операцией, либо вами, либо фреймворком, таким как Hibernate. Помните, аннотации - это просто метаданные: если никто не интерпретирует эти метаданные, это не добавляет поведения и не влияет на работающую программу.
Все это, как говорится, я настоятельно рекомендую не вводить ServletContext
в сущность. Объекты являются частью вашей доменной модели и должны быть отделены от любого механизма доставки, такого как уровень веб-доставки на основе сервлетов. Как вы будете использовать эту сущность, когда к ней обращается клиент командной строки или что-то еще, не связанное с ServletContext? Вы должны извлечь необходимые данные из этого ServletContext и передать их через аргументы традиционного метода вашей сущности. Благодаря этому подходу вы достигнете гораздо лучшего дизайна.
20 плюса
Да, конечно ты можешь. Вам просто нужно убедиться, что сущность также зарегистрирована как управляемый компонент Spring либо декларативно с использованием <bean>
тегов (в некотором spring-context.xml), либо с помощью аннотаций, как показано ниже.
Используя аннотации, вы можете пометить свои объекты @Component
(или более конкретным стереотипом, @Repository
который включает автоматический перевод исключений для DAO и может или не может мешать JPA).
@Entity
@Component
public class MyJAPEntity {
@Autowired
@Transient
ServletContext servletContext;
...
}
После того, как вы сделали это для своих сущностей, вам нужно настроить их пакет (или некоторый пакет предков) для сканирования Spring, чтобы сущности выбирались как бины, а их зависимости автоматически подключались.
<beans ... xmlns:context="..." >
...
<context:component-scan base-package="pkg.of.your.jpa.entities" />
<beans>
РЕДАКТИРОВАТЬ : (что, наконец, сработало и почему)
Создание
ServletContext
статики . (удалить @Autowired )@Transient private static ServletContext servletContext;
Поскольку JPA создает отдельный экземпляр сущности, т. Е. Не использует управляемый bean-компонент Spring, он необходим для совместного использования контекста .
Добавление метода @PostConstruct
init()
.@PostConstruct public void init() { log.info("Initializing ServletContext as [" + MyJPAEntity.servletContext + "]"); }
Это срабатывает init()
после создания экземпляра сущности и, ссылаясь ServletContext
внутри, вызывает принудительное внедрение статического свойства, если оно еще не введено.
Переход
@Autowired
к методу экземпляра, но установка статического поля внутри.@Autowired public void setServletContext(ServletContext servletContext) { MyJPAEntity.servletContext = servletContext; }
Цитируя мой последний комментарий ниже, чтобы ответить, почему мы должны использовать эти махинации:
Автор: Ravi Thapliyal Размещён: 10.05.2013 06:58Нет хорошего способа сделать то, что вы хотите, поскольку JPA не использует контейнер Spring для создания экземпляров своих сущностей. Думайте о JPA как об отдельном контейнере ORM, который создает экземпляр жизненного цикла сущностей и управляет им (полностью отделенный от Spring) и выполняет DI только на основе взаимосвязей сущностей.
1 плюс
После долгого времени я наткнулся на этот SO ответ, который заставил меня задуматься об элегантном решении:
- Добавьте к своим сущностям все необходимые поля @Transient @Autowired
- Создайте @Repository DAO с этим автоматическим полем:
@Autowired private AutowireCapableBeanFactory autowirer;
- Из вашего DAO, после извлечения сущности из БД, вызовите этот код автоматического подключения:
String beanName = fetchedEntity.getClass().getSimpleName(); autowirer.autowireBean(fetchedEntity); fetchedEntity = (FetchedEntity) autowirer.initializeBean(fetchedEntity, beanName);
Затем ваша сущность сможет получить доступ к полям с автопроводкой, как любой @Component.
Автор: xtian Размещён: 13.11.2017 10:17Вопросы из категории :
- spring Получение Spring Application Context
- spring BeanFactory против ApplicationContext
- spring Тип безопасности: непроверенный актерский состав
- spring Код модульного тестирования, отправляющий сообщения JMS
- spring Grails, вставка большого количества данных с использованием результатов withTransaction в OutOfMemoryError
- spring Каковы преимущества Apache Wicket?
- spring-mvc jdo интеграция с весной ..?
- spring-mvc Как обрабатывать статический контент в Spring MVC?
- spring-mvc Проверка заголовков запросов с помощью среды проверки Spring
- spring-mvc Возможно ли использовать Spring MVC с Groovy или Scala?
- spring-mvc как настроить многие DispatcherServlet весной 3 мвс?
- spring-mvc Триггер 404 в контроллере Spring-MVC?
- jpa Hibernate JPA Sequence (без идентификатора)
- jpa Как сохранить свойство типа List <String> в JPA?
- jpa Как сохранить дату / время и временные метки в часовом поясе UTC с JPA и Hibernate
- jpa Где я могу найти список всех ключевых слов HQL?
- jpa org.hibernate.annotations против javax.persistence
- jpa Проблема при получении Hibernate EntityManagerFactory в Weblogic (приложение EJB3)