Spring is ignoring @Transactional annotations in Apache Shiro Realm class

左心房为你撑大大i 提交于 2019-12-05 06:25:54
Jensen Ching

The root cause of the issue is in fact due to the following:

All BeanPostProcessors and their directly referenced beans will be instantiated on startup... Since AOP auto-proxying is implemented as a BeanPostProcessor itself, no BeanPostProcessors or directly referenced beans are eligible for auto-proxying (and thus will not have aspects 'woven' into them.

Referenced SO question is here.

I have resolved this issue by decoupling the Realm bean creation from the SecurityManager bean creation.

The relevant change is from the following code:

@Bean
@Autowired
public DefaultWebSecurityManager securityManager(MainRealm mainRealm) {
    final HashedCredentialsMatcher hcm = new HashedCredentialsMatcher(shiroHash);
    hcm.setHashIterations(shiroIter);
    hcm.setStoredCredentialsHexEncoded(shiroHexEncoded);
    mainRealm.setCredentialsMatcher(hcm);
    final DefaultWebSecurityManager sm = new DefaultWebSecurityManager();
    sm.setRealm(mainRealm);
    return sm;
}

to the following code:

@Bean
public DefaultWebSecurityManager securityManager() {
    final DefaultWebSecurityManager sm = new DefaultWebSecurityManager();
    //sm.setRealm(mainRealm); -> set this AFTER Spring initialization so no dependencies
    return sm;
}

Then I use a ServletContextListener which listens to when the Spring context initialization completes and I have the both the MainRealm and SecurityManager beans. Then I just plug one bean inside another.

@Override
public void contextInitialized(ServletContextEvent sce) {
    try {

        //Initialize realms
        final MainRealm mainRealm = (MainRealm)ctx.getBean("mainRealm");
        final DefaultWebSecurityManager sm = (DefaultWebSecurityManager)ctx.getBean("securityManager");
        sm.setRealm(mainRealm);
    } catch (Exception e) {
        System.out.println("Error loading: " + e.getMessage());
        throw new Error("Critical system error", e);
    }
}

@Transactional annotation can be used before :

  • An interface def
  • An interface method
  • A class def
  • A PUBLIC method of a class

As explained in the documentation

The fact that your method is protected must be the reason of your problem, and your service method was maybe declared as public which would explained why it worked in that case

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!