赞
踩
使用@Autowired可以注入一个bean进来
- @Autowired
- private Diana diana;
那么如果在容器中没有Diana
的对象被实例化的时候应用程序会报错吗?我们可以通过把Diana
上面的@Component注释掉来看一下结果如何
- //@Component
- public class Diana {
- public void r(){
- System.out.println("Diana R");
- }
- }
-
- @RestController
- @RequestMapping("/v1/banner")
- public class BannerController {
- @Autowired
- private Diana diana;
- }
启动SpringBoot会出现以下结果:
由此可见,如果spring无法在容器中找到Diana
的对象,在默认的机制下启动时就会直接报错。
当在@Autowired后面加上 (required = false),变成
- @RestController
- @RequestMapping("/v1/banner")
- public class BannerController {
-
- @Autowired(required = false)
- private Diana diana;
-
- @GetMapping("/test")
- public String test1() {
- diana.r();
- return "Hello test1";
- }
- }
SpringBoot可以 正常启动,但是当访问diana下面的方法时会出现下面这样的结果
出现这样的情况注入是没有问题的,而是由于容器中没有diana这个对象却又调用diana下面的方法
结论:
_如果spring无法在容器中找到Diana的对象,在默认的机制下启动时就会直接报错。我们可以通过@Autowired(required = false)的方式令应用程序可以正常启动。 _
依赖注入时机
IOC容器究竟是在什么时候实例化对象并把对象注入到代码片段里的呢?是当请求访问Controller的时候才进行实例化并注入,还是在SpringBoot应用启动时就开始实例化并把对象注入到代码片段的呢?
由之前的代码可以看出,当把Diana上面的@Component注释掉时,SpringBoot应用启动时应用程序会立即报错,我们也可以通过在Diana这个类中加一个无参的构造方法来验证以下
- @Component
- public class Diana {
- public Diana() {
- System.out.println("Hello Diana");
- }
- public void r(){
- System.out.println("Diana R");
- }
- }
应用程序启动时控制台打印出了"Hello Diana"
结论:
默认机制下,在SpringBoot应用启动时,IOC容器就开始实例化对象并把对象注入到代码片段里
SpringBoot默认是立即实例化的机制,我们可以通过 @Lazy让它变成延迟实例化。
- @Component
- @Lazy
- public class Diana {
当只在Diana上加上 @Lazy,启动应用却发现Diana仍然是立即实例化,@Lazy并没有起作用。这是因为BannerController是立即实例化的,那它下面的属性如果是@Autowired的就也需要立即实例化,只加在Diana上的 @Lazy是会被忽略掉的。如果真的需要延迟实例化就需要在BannerController也加上@Lazy或者是BannerController注入Diana的地方加上@Lazy,示例代码如下:
- @RestController
- @RequestMapping("/v1/banner")
- @Lazy
- public class BannerController {
或者
- @Autowired
- @Lazy
- private Diana diana;
当访问当前的Controller控制台打印出了下面的结果:
由此可见,此时是当请求访问Controller的时候才进行实例化并注入
如果没有特殊理由最好不要开启延迟实例化。使用默认机制提前实例化才是一个比较好的做法,因为可以尽早发现问题,避免很多问题在运行时才被发现。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。