【发布时间】:2016-01-01 06:30:33
【问题描述】:
我有一个使用 Hibernate 4.3.8 作为 JPA 提供程序的 Spring Framework 4 应用程序。我想使用 Hibernate 过滤器,因此我需要启用它们。我想在应用程序中全局执行此操作,我正在尝试使用 Spring AOP 执行此操作。我的想法是,我可以编写一个方面,在每次创建/获取会话时启用过滤器,例如 this 和 this 问题。
我已将 spring-aop 和 aspectjweaver 依赖项添加到我的项目中(使用 Maven)。我添加了以下方面。
@Aspect
@Component
public class EnableHibernateFilters {
@Pointcut("execution(* org.hibernate.SessionFactory.getCurrentSession(..))")
protected void sessionBeingFetched() {
}
@AfterReturning(pointcut = "sessionBeingFetched()", returning = "object")
public void enableFilters(JoinPoint joinPoint, Object object) {
System.out.println("!!! Enabling filters !!!"); // Never printed
Session session = (Session) object;
session.enableFilter("myFilter");
}
}
我的问题是上述建议 (enableFilters) 从未被调用过;既没有打印文本,也没有启用我的过滤器。我已经通过将切入点更改为我自己的类之一来验证检测到我的方面并且 AOP 在我的项目中有效。我也尝试将切入点更改为execution(* org.hibernate.SessionFactory.openSession(..)),但没有结果。
我怀疑这是我设置 Hibernate 的方式造成的,因为我没有明确配置 SessionFactory;相反,我设置了一个EntityManagerFactory。这是我的配置。
@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
@Bean
public DataSource dataSource() throws NamingException {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/postgres"); // JNDI lookup
}
@Bean
public EntityManagerFactory entityManagerFactory() throws SQLException, NamingException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setDatabase(Database.POSTGRESQL);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan(...);
factory.setDataSource(this.dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public JpaTransactionManager transactionManager() throws SQLException, NamingException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(this.entityManagerFactory());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
基本上我不确定在上述配置中使用哪个切入点。我试图弄乱LocalContainerEntityManagerFactoryBean.setLoadTimeWeaver(),但我想不通。我不知道我是否还需要配置它。
基本上,我的 AOP 设置适用于我自己的自定义类。我想问题可能是编织没有配置 Hibernate 或其他东西(我对这部分内容非常不熟悉),或者由于我的设置,会话不是通过 SessionFactory.getCurrentSession() 方法获得的。我试图通过将切入点更改为execution(* org.hibernate.Hibernate.isInitialized(..)) 并在我的代码中手动调用Hibernate.isInitialized(null) 来验证我的建议是否适用于Hibernate,但这也没有触发建议,所以这可能是问题所在。我尝试了this post to enable Hibernate weaving 中的建议,但我无法让它产生任何影响。
我也尝试将我的切入点设置为execution(* org.springframework.orm.hibernate4.SessionHolder.getSession(..)) 和execution(* org.springframework.orm.jpa.vendor.HibernateJpaDialect.getSession(..)),但也没有任何运气。
所以,我不确定下一步该去哪里。如何从我的建议中获取 Hibernate 的 Session 对象,以便启用 Hibernate 过滤器?提前谢谢!
编辑:
以防万一,我的配置中确实存在@EnableAspectJAutoProxy:
@Configuration
@ComponentScan(basePackages = { ... })
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
// ...
}
【问题讨论】:
-
也许
@ComponentScan("org.hibernate")有帮助? -
@Ruben 不,这没什么区别。
-
您正在拦截
SessioNFactory,但使用的是普通的JPA(使用hibernate作为实现者)。这显然永远不会开始,您的配置中没有SessionFactory,因此您的方面将不匹配任何内容。改写EntityManagerFactory.getEntityManager的切入点。 -
@M.Deinum 这是有道理的。我试过了,但无法让它工作。如果我定义了
@EnableAspectJAutoProxy(proxyTargetClass = true),我会得到以下异常:java.lang.IllegalArgumentException: Cannot subclass final class。如果我删除注释,那么我的项目会编译,但切入点不起作用。我直接在LocalContainerEntityManagerFactoryBean上尝试了各种切入点,但到目前为止没有运气。 -
而你的
AppConfig和PersistenceConfig是在同一个上下文中加载的? AOP 仅适用于在同一应用程序上下文中定义的 bean。
标签: java spring hibernate spring-aop