为什么在春天没有DI的情况下缓存不起作用?

时间:2019-07-31 08:10:15

标签: java spring spring-boot

说我有一个Rest控制器:

@RestController
public class FooController {
    /* foobar instantiation/declaration goes here */

    @RequestMapping("/foo")
    public String bar(@RequestParam(value = "baz") String baz) {
        return foobar.createResponse(baz);
    }
}

createResponse()方法带有@Cacheable注释。 当我像private Foobar foobar = new Foobar();那样实例化foobar时,缓存不起作用。 但是,当使用@Autowired private Foobar foobar;之类的东西时,缓存就可以了。

我一直在四处看看,据我所知,Spring在缓存中使用代理类。所以我的问题是,如果没有某种依赖注入,就不能使用缓存吗?是因为Spring必须注入代理类吗? 谢谢!

4 个答案:

答案 0 :(得分:1)

  

所以我的问题是,如果没有某种方式,您是否不能使用缓存   依赖注入

依赖注入不是问题的原因。问题是您想使用Spring功能,但是只要这些功能由Spring管理(通常称为Spring Bean),就能使用所需的特定或横向功能(此处为缓存功能)来使应用程序的对象赋权/丰富化的Spring功能起作用。 。
这对org.springframework.cache.annotation.Cacheable是正确的,但对于事务,注入,安全性,生成的实现等,也适用于Spring为我们的对象提供的功能。

您必须考虑Spring不会监视JVM中存在的所有对象。这会很复杂,非常慢,而且也不是所希望的,因为并不是所有对象都不是Spring Bean。

如果不想使此类成为bean,请不要将Spring用于缓存功能。例如,单独使用EhCache。但是结果是它只会使您编写更多样板代码。如果使用Spring,那将非常可惜。

答案 1 :(得分:1)

private Foobar foobar = new Foobar();中,您正在创建一个新对象,而不是从spring容器中取出一个对象,因此不会进行任何日志记录。

但是当您使用@Autowired private Foobar foobar;时,要取用由弹簧容器创建的对象,弹簧会将对象注入到该引用中。

答案 2 :(得分:1)

为了回答这个问题,您需要了解spring是如何工作的。 我将尽力提供一个简单的解释,尽管再一次,对spring作为框架的职责的深入了解肯定会在这里为您提供帮助。

启用缓存后,spring有效地将您的对象(在这种情况下为Foo)包装到某种运行时生成的代理中,从而增加了缓存功能。

现在,spring只能对它管理的对象执行此操作。

因此,如果您自己实例化FooFoo foo = new Foo())spring实际上已经不在游戏中,spring甚至不知道该对象存在。因此,当然,这里不会创建任何代理。请注意,即使Spring“知道”如何处理类型为Foo的对象(读取,在应用程序上下文中有类型为Foo的Bean),它也无法管理这个具体实例

现在,如果您使用自动装配(或一般来说注入依赖项),您会说完全不同的话:

  • Spring管理Bean Foo(如果spring无法创建该Bean的实例,则应用程序上下文将根本无法启动)
  • Spring使用代理包装依赖关系,该代理透明地添加了缓存功能,并将此依赖关系“绑定”(注入)到您的控制器中。

因此,spring现在可以完成工作-缓存工作:)

答案 3 :(得分:1)

使用new运算符创建新对象时,将由您自己实例化该对象,这意味着其生命周期不受Spring管理。

当您创建一个bean并对其进行自动装配时,其实例化将由spring框架进行管理。

在缓存的情况下,当您具有@Cacheable注释时,spring将返回一个代理而不是实际的实例化对象。代理负责缓存结果,并根据您提供的元数据(注释)放入和撤出缓存。