如何控制Bean的创建
通过上篇文章,我们知道了Spring Boot 中一个@Controller修饰的Bean是在什么时间被创建的,那么这个Bean创建时间能不能由我们管控?答案是肯定的
创建时机
我们知道Spring 中Bean都是由ApplicationContext这个容器来管控的,上一篇中,我们可以看到的结果是,在程序启动的时候,我们用@Controller 修改的Bean就被创建。那么我们可以想一想,如果我的程序到最后都没有用到这个Controller,那这个Controller 是不是就有点占用资源了。这个时候我们应该想到的就是懒加载<不知道懒加载是什么的同学自行百度哈~>。Spirng给我们提供了懒加载的配置。
首先我们来看一下默认加载
Spring Boot的启动方法
run()——>refreshContext()———->refresh() 中的finishBeanFactoryInitialization
有如下注释:
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
实例化非懒加载单例,(参考上一篇 地址文件头)我们可以得出结论,默认Bean的配置是non-lazy-init的
如何配置懒加载呢?
一个很简单方式 @Lazy 注解,改注解可以在类上和方法上添加,配置普通的@Bean的时候也可以加上改注解,实现Bean对象的懒加载
@Controller
@Lazy
@RequestMapping("/test")
public class TestController {
public TestController(){
System.out.println("TestController 创建了");
}
@GetMapping
@ResponseBody
public String getTest(){
return "aaa";
}
}
通过控制台我们可以看到,创建的TestController 的时机是在访问这个Controller的时候。
2018-07-03 16:11:49.224 INFO 844 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8888 (http)
2018-07-03 16:11:49.229 INFO 844 --- [ main] com.seven.App : Started App in 4.073 seconds (JVM running for 4.575)
2018-07-03 16:11:49.311 INFO 844 --- [nio-8888-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-07-03 16:11:49.311 INFO 844 --- [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2018-07-03 16:11:49.389 INFO 844 --- [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 78 ms
TestController 创建了
开发中碰到的问题
这边给大家提一个问题,有开发经验的同学在一般的web项目中会分三层,Controller Service Dao,在Controller 中,我们经常会这样写:
Controller层
@Controller
//@Lazy
@RequestMapping("/test")
public class TestController {
@Autowired
private ITestService testService;
public TestController(){
System.out.println("TestController 创建了");
}
@GetMapping
@ResponseBody
public String getTest(){
return "aaa";
}
}
Service 层
//@Service
public class TestService implements ITestService {
}
有时候我们忘记了在Service 的实现类上面加@Service注解,启动的时候,会报错,你知道报的错是什么吗?如果在Controller上面加上@Lazy注解,会在访问Controller 的时候报错。 如果看到这里你还不知道答案的话,建议再把上面一节看一下。这里就不细说了,留给各位童鞋一点思考的空间。
总结
- 创建Bean的时机有两种选择
一. 采用默认的方式,不加额外的配置,在启动程序的时候加载并创建好
二. 通过设置懒加载(non-lazy-init) @Lazy 注解
问题
容器管控的Bean在创建的时候,不管是lazy-init还是non-lazy-init 默认都是单例的,如果我想每次都拿到一个新的Bean,如何配置呢?
深入理解Spring —— Bean的更新