Spring Dependency Injection into JPA entity listener

前端 未结 3 715
礼貌的吻别
礼貌的吻别 2020-12-10 09:33

I need to have a Spring dependency injected into a JPA entity listener. I know I can solve this using @Configurable and Spring\'s AspectJ weaver as javaagent, but this seems

相关标签:
3条回答
  • 2020-12-10 10:11

    You can try this solution

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    
    public final class AutowireHelper implements ApplicationContextAware {
    
    private static final AutowireHelper INSTANCE = new AutowireHelper();
    private static ApplicationContext applicationContext;
    
    private AutowireHelper() {
    }
    
    /**
     * Tries to autowire the specified instance of the class if one of the specified beans which need to be autowired
     * are null.
     *
     * @param classToAutowire        the instance of the class which holds @Autowire annotations
     * @param beansToAutowireInClass the beans which have the @Autowire annotation in the specified {#classToAutowire}
     */
    public static void autowire(Object classToAutowire, Object... beansToAutowireInClass) {
        for (Object bean : beansToAutowireInClass) {
            if (bean == null) {
                applicationContext.getAutowireCapableBeanFactory().autowireBean(classToAutowire);
                return;
            }
        }
    }
    
    /**
     * @return the singleton instance.
     */
    public static AutowireHelper getInstance() {
        return INSTANCE;
    }
    
    @Override
    public void setApplicationContext(final ApplicationContext applicationContext) {
        AutowireHelper.applicationContext = applicationContext;
    }
    

    }

    and then

     @Autowired
    SomeService thatToAutowire;
    
      AutowireHelper.autowire(this, this.thatToAutowire);//this in the method
    
    0 讨论(0)
  • 2020-12-10 10:15

    Another trick is to implement an utility class with static method that helps you to use Spring beans everywhere, not only in managed classes:

    @Component
    public final class BeanUtil {
    
        private static ApplicationContext context;
    
        private BeanUtil(ApplicationContext context) {
            BeanUtil.context = context;
        }
    
        public static <T> T getBean(Class<T> clazz) throws BeansException {
    
            Assert.state(context != null, "Spring context in the BeanUtil is not been initialized yet!");
            return context.getBean(clazz);
        }
    }
    
    0 讨论(0)
  • 2020-12-10 10:22

    Since Hibernate 5.3 org.hibernate.resource.beans.container.spi.BeanContainer and Spring 5.1 org.springframework.orm.hibernate5.SpringBeanContainer you do not need to extra autowiring effort any more. See details of this feature in https://github.com/spring-projects/spring-framework/issues/20852

    Simply annotate your EntityListener class with @Component, and do any autowiring like so:

    @Component
    public class MyEntityListener{
    
      private MySpringBean bean;
    
      @Autowired
      public MyEntityListener(MySpringBean bean){
        this.bean = bean;
      }
    
      @PrePersist
      public void prePersist(final Object entity) {
        ...
      }
    
    }
    

    In Spring Boot the configuration of LocalContainerEntityManagerFactoryBean is done automatically in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration.

    Outside of Spring Boot, you have to register SpringBeanContainer to Hibernate:

    LocalContainerEntityManagerFactoryBean emfb = ...
     emfb.getJpaPropertyMap().put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
    
    0 讨论(0)
提交回复
热议问题