阅读spring secirity源码,发现其中的代理模式用例
UserDetailsService接口
public interface UserDetailsService {
//~ Methods ========================================================================================================
/**
* Locates the user based on the username. In the actual implementation, the search may possibly be case
* insensitive, or case insensitive depending on how the implementation instance is configured. In this case, the
* <code>UserDetails</code> object that comes back may have a username that is of a different case than what was
* actually requested..
*
* @param username the username identifying the user whose data is required.
*
* @return a fully populated user record (never <code>null</code>)
*
* @throws UsernameNotFoundException if the user could not be found or the user has no GrantedAuthority
*/
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
//~ Methods ========================================================================================================
/**
* Locates the user based on the username. In the actual implementation, the search may possibly be case
* insensitive, or case insensitive depending on how the implementation instance is configured. In this case, the
* <code>UserDetails</code> object that comes back may have a username that is of a different case than what was
* actually requested..
*
* @param username the username identifying the user whose data is required.
*
* @return a fully populated user record (never <code>null</code>)
*
* @throws UsernameNotFoundException if the user could not be found or the user has no GrantedAuthority
*/
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
代理类CachingUserDetailsService
public class CachingUserDetailsService implements UserDetailsService {
private UserCache userCache = new NullUserCache();
private final UserDetailsService delegate;
CachingUserDetailsService(UserDetailsService delegate) {
this.delegate = delegate;
}
public UserCache getUserCache() {
return userCache;
}
public void setUserCache(UserCache userCache) {
this.userCache = userCache;
}
public UserDetails loadUserByUsername(String username) {
UserDetails user = userCache.getUserFromCache(username);
if (user == null) {
user = delegate.loadUserByUsername(username);
}
Assert.notNull(user, "UserDetailsService " + delegate + " returned null for username " + username + ". " +
"This is an interface contract violation");
userCache.putUserInCache(user);
return user;
}
private UserCache userCache = new NullUserCache();
private final UserDetailsService delegate;
CachingUserDetailsService(UserDetailsService delegate) {
this.delegate = delegate;
}
public UserCache getUserCache() {
return userCache;
}
public void setUserCache(UserCache userCache) {
this.userCache = userCache;
}
public UserDetails loadUserByUsername(String username) {
UserDetails user = userCache.getUserFromCache(username);
if (user == null) {
user = delegate.loadUserByUsername(username);
}
Assert.notNull(user, "UserDetailsService " + delegate + " returned null for username " + username + ". " +
"This is an interface contract violation");
userCache.putUserInCache(user);
return user;
}
}
其中UserCache为缓存类,接口如下
public interface UserCache {
//~ Methods ========================================================================================================
/**
* Obtains a {@link UserDetails} from the cache.
*
* @param username the {@link User#getUsername()} used to place the user in the cache
*
* @return the populated <code>UserDetails</code> or <code>null</code> if the user could not be found or if the
* cache entry has expired
*/
UserDetails getUserFromCache(String username);
/**
* Places a {@link UserDetails} in the cache. The <code>username</code> is the key used to subsequently
* retrieve the <code>UserDetails</code>.
*
* @param user the fully populated <code>UserDetails</code> to place in the cache
*/
void putUserInCache(UserDetails user);
/**
* Removes the specified user from the cache. The <code>username</code> is the key used to remove the user.
* If the user is not found, the method should simply return (not thrown an exception).
* <p>
* Some cache implementations may not support eviction from the cache, in which case they should provide appropriate
* behaviour to alter the user in either its documentation, via an exception, or through a log message.
*
* @param username to be evicted from the cache
*/
void removeUserFromCache(String username);
//~ Methods ========================================================================================================
/**
* Obtains a {@link UserDetails} from the cache.
*
* @param username the {@link User#getUsername()} used to place the user in the cache
*
* @return the populated <code>UserDetails</code> or <code>null</code> if the user could not be found or if the
* cache entry has expired
*/
UserDetails getUserFromCache(String username);
/**
* Places a {@link UserDetails} in the cache. The <code>username</code> is the key used to subsequently
* retrieve the <code>UserDetails</code>.
*
* @param user the fully populated <code>UserDetails</code> to place in the cache
*/
void putUserInCache(UserDetails user);
/**
* Removes the specified user from the cache. The <code>username</code> is the key used to remove the user.
* If the user is not found, the method should simply return (not thrown an exception).
* <p>
* Some cache implementations may not support eviction from the cache, in which case they should provide appropriate
* behaviour to alter the user in either its documentation, via an exception, or through a log message.
*
* @param username to be evicted from the cache
*/
void removeUserFromCache(String username);
}