Java Can';拦截器中的自动连线字段
我需要确定在数据库中存储对象时发生的事件。我使用拦截器。 拦截器类如下所示:Java Can';拦截器中的自动连线字段,java,spring,hibernate,Java,Spring,Hibernate,我需要确定在数据库中存储对象时发生的事件。我使用拦截器。 拦截器类如下所示: public class TaskInterceptor extends EmptyInterceptor { @Autowired private TaskNoticeRepository taskNoticeRepository;// my repository class @Transactional @Override public boolean onSave(Ob
public class TaskInterceptor extends EmptyInterceptor {
@Autowired
private TaskNoticeRepository taskNoticeRepository;// my repository class
@Transactional
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
return super.onSave(entity, id, state, propertyNames, types);
}
}
...<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="nestedTransactionAllowed" value="true"/>
</bean>
<bean id="taskInterceptor" class="ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="ru.librait.cs.model,ru.librait.cs.infrastructure.dto.export"/>
<property name="entityInterceptor" ref="taskInterceptor" />...
Spring配置文件如下所示:
public class TaskInterceptor extends EmptyInterceptor {
@Autowired
private TaskNoticeRepository taskNoticeRepository;// my repository class
@Transactional
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
return super.onSave(entity, id, state, propertyNames, types);
}
}
...<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="nestedTransactionAllowed" value="true"/>
</bean>
<bean id="taskInterceptor" class="ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="ru.librait.cs.model,ru.librait.cs.infrastructure.dto.export"/>
<property name="entityInterceptor" ref="taskInterceptor" />...
如何修复它?您创建了一个鸡蛋配置(或循环依赖项):要创建
会话工厂,您需要拦截器。拦截器需要回购协议。回购需要会话工厂
最简单的解决方案是注入ApplicationContext
并添加@PostConstruct
方法:
@Autowired
private ApplicationContext applicationContext;
private TaskNoticeRepository taskNoticeRepository;
@PostConstruct
public void init() {
taskNoticeRepository = applicationContext.getBean(TaskNoticeRepository.class);
}
这将设置步骤向后移动了一点,通常可以正常工作,但很脆弱
对于类似的事情,我更喜欢使用“init bean”,当应用程序启动时(在main()
或servlet上下文侦听器中)我从应用程序上下文中获得它,它在创建所有bean之后但在任何“正常”代码有机会运行之前连接这些依赖项
因此会有一个懒惰的initbean,它依赖于拦截器和repo。拦截器将获得一个用于回购的setter。bean将有一个公共的init()
方法来调用setter
这就避免了各种可能有效或可能无效的“神奇”设置代码。问题是循环依赖,是糟糕的设计。。但是你可以试试
<bean id="taskInterceptor" class="ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor">
<property name="taskNoticeRepository" ref="taskNoticeRepository"/>
</bean>
并删除@Autowired
或者在TaskInterceptor上添加@Component注释,并从xml中删除bean声明,如果ApplicationContext也返回null,则实现ApplicationContextAware可以解决此问题
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContext implements ApplicationContextAware {
private static ApplicationContext context;
public static <T extends Object> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringContext.context = context;
}
}
你能发布整个堆栈跟踪吗?你能分享第二种方法的链接吗?不,你必须仔细阅读我的答案,理解基本概念并将其应用于你的情况。