使用Spring AOP配置Hibernate会话

And*_*708 8 java spring hibernate spring-aop

我有一个Spring Framework 4应用程序,它使用Hibernate 4.3.8作为JPA提供程序.我想使用Hibernate过滤器,因此我需要启用它们.我想在应用程序中全局执行此操作,我正在尝试使用Spring AOP.我的想法是,我可以编写一个方面,每次创建/获取会话时启用过滤器,就像在这个这个问题中一样.

我已将spring-aopaspectjweaver依赖项添加到我的项目中(使用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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是enableFilters从不调用上面的advice(); 既没有打印文本,也没有启用我的过滤器.我已经通过将切入点更改为我自己的一个类来验证我的方面已被检测到并且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();
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上我不确定使用上述配置的切入点.我试图搞砸了LocalContainerEntityManagerFactoryBean.setLoadTimeWeaver(),但我无法理解.我不知道我是否还需要配置它.

从本质上讲,我的AOP设置适用于我自己的自定义类.我想问题是编织没有配置Hibernate或其他东西(我对这一部分非常不熟悉)或者SessionFactory.getCurrentSession()由于我的设置而没有通过该方法获得会话.我尝试通过将我的切入点更改为execution(* org.hibernate.Hibernate.isInitialized(..))Hibernate.isInitialized(null)在我的代码中手动调用来验证我的建议甚至可以使用Hibernate ,但这也没有触发建议,所以这可能是问题.我尝试了这篇文章中的建议,以启用Hibernate编织,但我无法让它有所作为.

我也试过我的切入点设置为execution(* org.springframework.orm.hibernate4.SessionHolder.getSession(..))execution(* org.springframework.orm.jpa.vendor.HibernateJpaDialect.getSession(..)),也没有任何的运气.

所以,我不知道下一步该去哪里.如何Session从我的建议中获取Hibernate的对象,以便我可以启用Hibernate过滤器?先感谢您!

编辑: 以防万一,我确实有@EnableAspectJAutoProxy我的配置:

@Configuration
@ComponentScan(basePackages = { ... })
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

Fil*_*lip 1

也许这只是您通过使用接口org.hibernate.SessionFactory作为执行参数来声明切入点的事实......

\n\n

@Pointcut("execution(* org.hibernate.SessionFactory.getCurrentSession(..))")

\n\n

正确的方法是将切入点的执行定义为该接口的实现,其符号略有不同,请参阅+符号

\n\n

@Pointcut("execution(* org.hibernate.SessionFactory+.getCurrentSession(..))")

\n\n

还有一种替代符号...

\n\n

@Pointcut("within(org.hibernate.SessionFactory+) && execution(* getCurrentSession(..))")

\n\n

你还应该看看aspectj-cheat-sheet

\n\n

关于java.lang.IllegalArgumentException: Cannot subclass final class.\n目标类是具体实现,org.hibernate.SessionFactoryorg.hibernate.internal.SessionFactoryImpl它恰好是最终的,public final class SessionFactoryImpl.

\n\n

配置proxyTargetClass = true根据文档

\n\n
\n

指示是否要创建基于子类 (CGLIB) 的代理,而不是创建基于标准 Java 接口的代理。

\n
\n\n

但是,由于您尝试子类化的类final根据但是,根据Java 语言规范,

\n\n
\n

如果 Final 类的名称出现在另一个类声明的 extends 子句 (\xc2\xa78.1.4) 中,则会出现编译时错误;这意味着最终类不能有任何子类。

\n
\n