与Spring框架的提交相关:https://github.com/spring-projects/spring-framework/commit/5aefcc802ef05abc51bbfbeb4a78b3032ff9eee3
初始化从afterPropertiesSet()更改为afterSingletonsInstantiated(),即延后了初始化阶段。
简而言之: 这样做可以避免在@PostConstruct使用缓存时出现问题。
详细说明: 这样做可以避免以下情况:
create serviceB with @Cacheable on a methodB
create serviceA with @PostConstruct calling serviceB.methodB
@Component public class ServiceA{ @Autowired private ServiceB serviceB; @PostConstruct public void init() { List<String> list = serviceB.loadSomething(); }
protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
// check whether aspect is enabled
// to cope with cases where the AJ is pulled in automatically
if (this.initialized) {
//>>>>>>>>>>>> NOT Being called
Class<?> targetClass = getTargetClass(target);
Collection<CacheOperation> operations = getCacheOperationSource().getCacheOperations(method, targetClass);
if (!CollectionUtils.isEmpty(operations)) {
return execute(invoker, new CacheOperationContexts(operations, method, args, target, targetClass));
}
}
//>>>>>>>>>>>> Being called
return invoker.invoke();
}
我的解决方法是手动调用初始化方法:
@Configuration
public class SomeConfigClass{
@Inject
private CacheInterceptor cacheInterceptor;
@PostConstruct
public void init() {
cacheInterceptor.afterSingletonsInstantiated();
}
当然,这解决了我的问题,但除了被调用两次(手动调用和框架预期的一次)之外,它是否有其他副作用?
我的问题是: “这是一个安全的解决方法吗?因为最初的提交者似乎对仅使用afterPropertiesSet()存在问题。”
@PostConstruct
不保证代理已经被创建(这也是为什么@Transactional
不能用于@PostConstruct
方法的原因)。@PostConstruct
方法在构造函数和依赖注入之后立即调用,但几乎总是在代理被创建之前。你为什么需要在@PostConstruct
方法中使用它?通常情况下,实现SmartInitializingSingleton
接口比使用@PostConstruct
更好,或者使用ApplicationListener<ContextRefreshedEvent>
。 - M. Deinum