Spring MongoDB和Apache Shiro
我试图使用Apache Shiro与Spring和MongoDB。 我正在使用自动assembly的Spring Data Repositories。 我为Shiro创建了自己的自定义域,它使用Spring Data存储库与Mongo交谈:
public class PlatformRealm extends AuthorizingRealm { @Autowired(required = true) protected UserRepository userRepository = null; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { ... } }
我看到的问题是userRepository没有自动assembly。 我在控制台输出中得到以下行,引用PlatformRealm:
INFO org.springframework.web.context.support.XmlWebApplicationContext - Bean 'platformRealm' of type [class com.resonance.platform.core.security.PlatformRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
这是因为Apache Shiro ShiroFilterFactoryBean。 发生了什么事情是这个bean及其所有依赖项在容器启动时立即被加载。 在解析依赖项之前,它不会等待我的持久性bean被初始化。 这会导致存储库引用为null。
通过contextConfigLocation参数加载以下bean配置:
contextConfigLocation /WEB-INF/web-platform-persistence.xml, /WEB-INF/web-platform-services.xml
服务bean配置:
<!-- --> # some example chain definitions: /admin/** = passThruFilter, roles[admin] /** = passThruFilter <!-- -->
持久性bean配置:
用户存储库:
package com.resonance.platform.core.data.repositories; import org.bson.types.ObjectId; import org.springframework.data.repository.CrudRepository; import com.resonance.platform.core.entities.User; /** * A repository used to manage User entities. * @author Kyle */ public interface UserRepository extends CrudRepository { /** * Gets a user by the specified login. * @param login * @return */ User getByLogin(String login); }
我的问题是,如何正确解析userRepository依赖关系? 我知道ShiroFilterFactoryBean必须在其他依赖项和诸如此类之前初始化,但必须有一种方法来解析userRepository依赖项。
编辑:添加了用户存储库代码。
我遇到了这里描述的同样问题。 我注意到两个spring的工厂。
- 来自dispacher-servlet.xml由于在基本包级别定义的组件扫描而加载@Service @Repository类,因此我可以@Autowire Service类进入Controller。
- 来自应用程序上下文似乎没有将@Autowire类标记为@Service,因为它们未加载。
如果我理解正确,你应该能够创建一个实现org.springframework.beans.factory.InitializingBean
的ShiroFilterFactoryBean
的子类。 在InitializingBean.afterPropertiesSet()
您将添加一些获取UserRepository
并将其设置为该字段的代码。 不是最优雅的解决方案,但这看起来像一个特例。
我也遇到过这个问题。 它与Spring容器中bean初始化的顺序有关。 解决方法不是自动assembly存储库,而是让您的领域实现ApplicationContextAware并直接从上下文获取所需的bean。 它不优雅,但它会起作用。
我不太确定这是否有用,但您可以向我查看这个问题以寻找替代解决方案。
但是,核心问题可能仍然存在。
从ShiroFilterFactoryBean-and-a-spring-data-mongodb-realm获取的具体问题解释:
问题是spring-data-mongodb需要一个Spring ApplicationEventMulticaster在它可以使用之前已经初始化。
ShiroFilterFactoryBean是一个beanPostProcessor,因此,在初始化期间,spring尝试配置它的领域(因此我的领域和spring数据mongo基于userDao)。 它失败,因为还没有创建ApplicationEventMulticaster。
在我尝试了几种建议的方法来解决这个问题之后,比如InitializingBean
, ApplicationContextAware
或BeanPostProcessor
接口(每个都导致过早的调用,因此在初始化我必要的服务/存储库之前),我提出了以下解决方案:
- 让spring创建你的shiro上下文,而不需要对服务/存储库进行任何自动bean解析。
- 让spring创建您的服务/存储库上下文,包括mongodb
- 创建一个简单的类,它将处理你的shiro-service耦合并在spring配置中相应地配置它。 在成功设置shiro和服务上下文后,将调用此类。
至(1),某事。 像这样:
/>
至(2),某事。 像这样:
...
至(3):
public class ShiroRealmServiceBridge { public static void postInject( MyShiroServerRealm realm, MyService service ) { realm.setService( service ); } } com.acme.ShiroRealmServiceBridge postInject
优点:
- 它适用于xD
- 没有额外的负担/依赖你的shiro东西
- 完整的弹簧配置和设置,在初始化后产生一致的状态
坏处:
- 一次性开销设置
- 可能会导致状态不一致,如果您忘记或碰撞胶水配置,则会在运行时而不是在启动时抱怨
ShiroFilterFactoryBean实现了BeanPostProcessor,因为它依赖于安全管理器w /它自己对数据存储,数据访问对象等的依赖性,它可能导致一大堆Y类型的Bean X没有资格被所有人处理BeanPostProcessors消息。
最糟糕的是,它似乎只是一种方式来查看Spring实例化的Filter实现,以便跟踪并可能将属性注入AuthorizationFilters。
坦率地说,我不需要为filter跟踪而头疼,所以我创建了一个不包含BeanPostProcessor的自定义版本。 我现在被迫手动将Filter实现连接到bean“filters”属性,但至少我不必处理该错误以及我的安全管理器和相关bean的可疑状态。