【发布时间】:2015-04-05 16:03:46
【问题描述】:
与spring框架https://github.com/spring-projects/spring-framework/commit/5aefcc802ef05abc51bbfbeb4a78b3032ff9eee3中的commit相关
初始化设置为从 afterPropertiesSet() 到 afterSingletonsInstantiated() 的后期阶段
简而言之: 这可以防止缓存在 @PostConstruct 用例中使用时起作用。
加长版: 这可以防止您使用的用例
在方法 B 上使用 @Cacheable 创建 serviceB
-
使用@PostConstruct 调用 serviceB.methodB 创建 serviceA
@Component public class ServiceA{ @Autowired private ServiceB serviceB; @PostConstruct public void init() { List<String> list = serviceB.loadSomething(); }
这导致 org.springframework.cache.interceptor.CacheAspectSupport 现在没有被初始化,因此没有缓存结果。
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();
}
这当然解决了我的问题,但除了被调用 2 次(1 次手动调用和 1 次按预期由框架调用)之外,它是否有副作用
我的问题是: “这是一个安全的解决方法吗,因为最初的提交者似乎在使用 afterPropertiesSet() 时遇到了问题”
【问题讨论】:
-
@PostConstruct不保证代理已经创建(这就是为什么@Transactional不适用于@PostConstruct方法的原因。@PostConstruct方法在之后调用构造和注入依赖项之后,但几乎总是在创建代理之前。为什么在@PostConstruct方法中需要它?通常ApplicationListener<ContextRefreshedEvent>比实现SmartInitializingSingleton接口更好,而不是@987654333 @. -
感谢您的回复。我们使用 postconstruct 使用从另一个服务(其方法上有 @Cacheable )获取的值来初始化 bean 我们希望即使使用 postconstruct 也会缓存这些值。如果不是这种情况,那么 java 文档将使框架受益,因为其他开发人员可能也不知道这一点。将改为尝试 SmartInitializingSingleton。谢谢!
-
这在the reference guide 中进行了解释,请阅读该部分的最后一段。
标签: java postconstruct spring-cache