|
@@ -23,6 +23,55 @@ import org.springframework.security.core.userdetails.cache.NullUserCache;
|
|
import org.springframework.util.Assert;
|
|
import org.springframework.util.Assert;
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * Implementation of {@link UserDetailsService} that utilizes caching through a
|
|
|
|
+ * {@link UserCache}
|
|
|
|
+ * <p>
|
|
|
|
+ * If a null {@link UserDetails} instance is got from calling
|
|
|
|
+ * {@link UserCache#getUserFromCache(String)} to the {@link UserCache} got from
|
|
|
|
+ * {@link #getUserCache()}, the user load is deferred to the {@link UserDetailsService}
|
|
|
|
+ * provided during construction. Otherwise, the instance got from cache is returned.
|
|
|
|
+ * <p>
|
|
|
|
+ * It is initialized with a {@link NullUserCache} by default, so it's strongly recommended
|
|
|
|
+ * setting your own {@link UserCache} using {@link #setUserCache(UserCache)}, otherwise,
|
|
|
|
+ * the delegate will be called every time.
|
|
|
|
+ * <p>
|
|
|
|
+ * Utilize this class by defining {@link org.springframework.context.annotation.Bean} that
|
|
|
|
+ * encapsulates an actual implementation of {@link UserDetailsService} and set an
|
|
|
|
+ * {@link UserCache}.
|
|
|
|
+ * </p>
|
|
|
|
+ * For example: <pre>{@code
|
|
|
|
+ * @Bean
|
|
|
|
+ * public CachingUserDetailsService cachingUserDetailsService(UserDetailsService delegate,
|
|
|
|
+ * UserCache userCache) {
|
|
|
|
+ * CachingUserDetailsService service = new CachingUserDetailsService(delegate);
|
|
|
|
+ * service.setUserCache(userCache);
|
|
|
|
+ * return service;
|
|
|
|
+ * }
|
|
|
|
+ * }</pre>
|
|
|
|
+ *
|
|
|
|
+ * <p>
|
|
|
|
+ * However, a preferable approach would be to use
|
|
|
|
+ * {@link org.springframework.cache.annotation.Cacheable} in your
|
|
|
|
+ * {@link UserDetailsService#loadUserByUsername(String)} implementation to cache
|
|
|
|
+ * {@link UserDetails} by <code>username</code>, reducing boilerplate and setup, specially
|
|
|
|
+ * if you are already using cache in your application.
|
|
|
|
+ * </p>
|
|
|
|
+ *
|
|
|
|
+ * For example:
|
|
|
|
+ *
|
|
|
|
+ * <pre>{@code
|
|
|
|
+ * @Service
|
|
|
|
+ * public class MyCustomUserDetailsImplementation implements UserDetailsService {
|
|
|
|
+
|
|
|
|
+ * @Override
|
|
|
|
+ * @Cacheable
|
|
|
|
+ * public UserDetails loadUserByUsername(String username) {
|
|
|
|
+ * //some logic here to get the actual user details
|
|
|
|
+ * return userDetails;
|
|
|
|
+ * }
|
|
|
|
+ * }
|
|
|
|
+ * }</pre>
|
|
|
|
+ *
|
|
* @author Luke Taylor
|
|
* @author Luke Taylor
|
|
* @since 2.0
|
|
* @since 2.0
|
|
*/
|
|
*/
|