根据Shiro 1.x的文档,SessionManager可以手动设置CacheManager,也可以配置一个`CacheManager`的bean,那么它是如何感知`CacheManager`的bean的呢。
我们首先看下SecurityManager接口继承结构:

public interface CacheManagerAware {
void setCacheManager(CacheManager var1);
}如果一个类实现了这个接口,那么将会调用setCacheManager来应用它。
它继承了Authenticator、Authorizer 和 SessionManager 接口,主要提供了login、logout和createSubject方法。这里没有涉及CacheManager接口。
public interface SecurityManager extends Authenticator, Authorizer, SessionManager
{
/**
* The CacheManager to use to perform caching operations to enhance performance. Can be null.
*/
private CacheManager cacheManager;
...
public CacheManager getCacheManager() {
return cacheManager;
}
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
afterCacheManagerSet();
}
protected void afterCacheManagerSet() {
applyEventBusToCacheManager();
}
...
}它是一个抽象类,我们这里主要关注它实现了SecurityManager和CacheManagerAware接口。它包含一个CacheManger类型的字段,对于缓存的管理全部交给了子类。
public abstract class RealmSecurityManager extends CachingSecurityManager
它继承了CachingSecurityManager类,它维护一个Realm集合,如果Realm实现了CachingManagerAware接口,将设置它们的cacheManager。
public abstract class AuthenticatingSecurityManager extends RealmSecurityManage
这个类没有涉及CacheManager,这里不讨论。
public abstract class AuthorizingSecurityManager extends AuthenticatingSecurityManager
这个类没有涉及CacheManager,这里不讨论。
public abstract class SessionsSecurityManager extends AuthorizingSecurityManager {
private SessionManager sessionManager;
...
}这个类处理session操作,它持有一个Sessionmanager对象,将涉及session的操作,委托给它。
如果SessionManager实现了CacheMangerAware接口,它会设置CacheManager。
protected void applyCacheManagerToSessionManager() {
if (this.sessionManager instanceof CacheManagerAware) {
((CacheManagerAware) this.sessionManager).setCacheManager(getCacheManager());
}
}public class DefaultSecurityManager extends SessionsSecurityManager
没有涉及CacheManager的内容。
public class DefaultWebSecurityManager extends DefaultSecurityManager implements WebSecurityManager
没有涉及CacheManager的内容。
======================================= spring自动配置
先看类图:

public class AbstractShiroConfiguration {
@Autowired(required = false)
protected CacheManager cacheManager;这个配置类,尝试注入CacheManager。
它通过securitymanager方法,配置默认的SessionsSecurityManager:
protected SessionsSecurityManager createSecurityManager() {
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setSubjectDAO(subjectDAO());
securityManager.setSubjectFactory(subjectFactory());
RememberMeManager rememberMeManager = rememberMeManager();
if (rememberMeManager != null) {
securityManager.setRememberMeManager(rememberMeManager);
}
return securityManager;
}
protected SessionsSecurityManager securityManager(List<Realm> realms) {
SessionsSecurityManager securityManager = createSecurityManager();
securityManager.setAuthenticator(authenticator());
securityManager.setAuthorizer(authorizer());
securityManager.setRealms(realms);
securityManager.setSessionManager(sessionManager());
securityManager.setEventBus(eventBus);
if (cacheManager != null) {
securityManager.setCacheManager(cacheManager);
}
return securityManager;
}@Configuration
@SuppressWarnings("SpringFacetCodeInspection")
@ConditionalOnProperty(name = "shiro.enabled", matchIfMissing = true)
public class ShiroAutoConfiguration extends AbstractShiroConfiguration这里我们关心的只是securityManager(List<Realm> realms)方法:
@Bean
@ConditionalOnMissingBean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
return super.securityManager(realms);
}它只是调用AbstractShiroConfiguration#securityManager方法。
@Configuration @AutoConfigureBefore(ShiroAutoConfiguration.class) @AutoConfigureAfter(ShiroWebMvcAutoConfiguration.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true) public class ShiroWebAutoConfiguration extends AbstractShiroWebConfiguration
这里我们关心的只是securityManager(List<Realm> realms)方法,仅是调用父类的方法而已:
@Bean
@ConditionalOnMissingBean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
return super.securityManager(realms);
}@Configuration @AutoConfigureBefore(ShiroAutoConfiguration.class) @AutoConfigureAfter(ShiroWebMvcAutoConfiguration.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true) public class ShiroWebAutoConfiguration extends AbstractShiroWebConfiguration
这里我们关心的只是securityManager(List<Realm> realms)方法,仅是调用父类的方法而已:
@Bean
@ConditionalOnMissingBean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
return super.securityManager(realms);
}这个是用于普通的Spring程序的配置类。