Spring原理
1.Bean的作用域和生命周期
2.Spring自动装配的流程
Bean的作用域
作用域是啥?
作用域知道是Bean在Spring框架中的某种行为模式,比如单例模式作用域表示Bean在spring中只有一份,是全局共享的,只要有一个人修改,其他人也会看到
作用域分为六种
单例作用域(Singleton)
Dog类
这个类只是一个普通的类,他并没有交给springioc容器进行管理
DogBeanConfig类
这个类加了一个@Component注解,所以会被spring扫描到,接着他的方法中有一个加了@Bean注解,虽然Dog类没有加上注解,但是这里的方法已经把Dog给实例化了,所以后续的getBean(Dog.class)可以获取到Dog类
在容器中多次获取Bean
结果
总结
多次获取Bean并输出对象的地址,发现地址是一样的,说明每次在springIOC
中取出来的对象都是同一个,这就是单例模式,默认情况下,spring中的bean都是单例模式
多例作用域Prototype
每次使用该bean的时候,都会创建一个新的实例
需要加一个@Scope注解
结果
这样在多次获取这个scope的时候,就会自动生成新的实例
Web相关作用域
请求作用域request
需要加一个@RequestScope注解
结果
一次请求,就只有一个对象,每次请求,都会创建一个新的对象
会话作用域session
需要加一个@SessionScope注解
结果
在一个会话中,只有一个对象,只有切换会话才会创建新的对象
Application作用域
需要加一个@Application注解
在一个应用中,只能访问到同一个对象,所有人共用的都是这一个,除非这个服务器重启。
websocket作用域
链接断开就换新的,否则一直是一个
Bean的生命周期
- 实例化(为Bean分配内存空间)createBeanInstance
- 属性赋值(Bean注入和装配)populateBean()
- Bean初始化 initializeBean()
- 执行各种通知
- 执行初始化方法
- 使用Bean
- 销毁Bean
流程图
代码示意图
结果
举例子
买毛胚房,自己装修水电门窗,然后等全部装好之后,清扫一次,然后入住,到期销毁结束。
SpringBoot自动配置
什么叫SpringBoot自动配置?
当Spring容器启动的时候,一些配置类,Bean对象就会自动传入到IOC容器中去,我们就不需要手动去声明
Spring是如何把对象加载到SpringIOC容器中去的
首先,我们知道只有通过五大注解和@Bean,才可以把数据交给IOC容器进行管理,前提是,这些注解类必须和启动类(@SpringBootApplication)处于同一个目录之下,但是我们引入的第三方的jar包,很明显不合这个启动类处于同一个目录,为什么能够启动?
如何解决这个问题?
- @ComponetScan组件扫描
当使用这个注解的时候,spring在启动的时候,就会自动扫描这个注解的组件,也可以扫描多个包
- @Import导入
- 直接导入类
可以导入一个类,也可以导入多个类
- 实现Importselector
实现importselector接口,把需要使用的类导入即可
缺点
这几种方式,都是需要知道第三方依赖中有哪些Bean对象或配置项,但是我们不可能知道所有的Bean,所以这个方法还是不适用
如何解决
解铃还需系铃人,这个代码是第三方写的,那么第三方肯定是知道需要使用哪些组件,哪些Bean是刚需,那只需要让第三方把全部事情做好,最后再给我提供一个注解
只需要让第三方自定义一个注解,然后把需要使用到的Bean全部放在一起,当我需要使用的时候,我只需要使用这个注解,那么我就可以使用到全部的
这种注解一般使用Enable开头
SpringBoot是如何实现自动配置的
核心就在于SpringBoot的启动类
@Target({ElementType.TYPE}):限定这个注解只能用在类、接口、枚举上(不能用在方法、字段等)。
@Retention(RetentionPolicy.RUNTIME):让注解在运行时依然保留,Spring 框架才能在启动时读取并解析它。
@Documented:标记这个注解会被包含在 JavaDoc 文档里。
@Inherited:如果一个类被此注解修饰,它的子类会自动继承这个注解(Spring Boot 场景下主要是为了兼容一些继承场景)。
核心
@SpringBootConfiguration
这个是一个加强版的@configuration,是一个加强版的配置类,作为配置文件,加速启动类,和configuration的功能基本一样,只是多了一层spring语义包装
@ComponenScan
这个是用来扫描特定的包,自动扫描被五大注解和bean标记的类,是他们注册成为spring bean
@EnableAutoConfiguration(灵魂)
@Import({AutoConfigurationImportSelector.class})
这一步,自动就把实现了importselecttor接口的类全部导入
这个selectImport方法就自动获取可以配置的配置类信息
继续点进去
基取所有基于 META INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imp orts ⽂件, META-INF/spring.factories ⽂件中配置类的集合.
在我们导入的依赖中,通常都会有这两个文件
1.@conditional注解
当自动加载配置类的时候,他不会一股脑全部加载进来,而是通过conditional注解,按照自己的判断,只有满足一定的条件,配置里面的才会生效
2.META-INF/spring.factories⽂件
这个是spring内部提供的一个加载方式,只需要在这个文件中配置即可,spring会把对应的实现类注入到spring容器中去
@AutoConfigurationPackage
Registrar实现了 ImportBeanDefinitionRegistrar 类,就可以被注解@Import导⼊到spring 容器⾥. (String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0]) :当前启动类所在的包名. 所以: @AutoConfigurationPackage 就是将启动类所在的包下⾯所有的组件都扫描注冊到 spring 容器中.
总结
当程序启动的时候,首先就会找到 @SpringBootApplication,然后 @ComponentScan 就会进行包扫描,扫描启动类所在的包及其子包;@SpringBootConfiguration 标记当前类是配置类(等价于 @Configuration);然后 @EnableAutoConfiguration 就会执行 @AutoConfigurationPackage,把启动类所在的根包位置记录下来并告知 Spring,供后续配置使用;@Import(AutoConfigurationImportSelector.class) 就会根据配置文件,按条件筛选并导入自动配置类。
在Spring与JDK中Bean的区别?
在Spring中,Bean表示的是被spring容器管理的Java对象,在JDK中,Bean表示的是普通的Java对象。
在Spring中,什么可以称之为Bean
被五大注解或者@Bean修饰的类或方法,都会被Spring Ioc实例化成Java对象,这些对象就叫做Spring Bean
五大注解:
@Component
@Service(业务层)
@Controller / @RestController(控制层)
@Repository(数据访问层)
@Configuration(配置类)
@Bean
依赖注入(DI)
@Autowired
Setter
构造方法
