黑白客 发表于 2023-1-4 10:14

spring提前加载,懒加载,bean的作用域和注入注解讲解

# 前言
sping知识随笔笔记;spring提前加载,懒加载,bean的作用域和注入注解讲解

---





# 1 depends-on
depends-on 是提前加载,比如在实体类a中 depends-on="d,c,b" 就会按照顺序优先执行 d c b a;

> 使用场景

`A在实例化之前必须要实例化B ,使用场景是:A需要实例化B,但是并没有使用B实例化的对象,使用Depends-on`

`如果A使用了B的实例:那么使用构造器注入或者其它注入方式更好,可以直接获取到实例化后的对象。`

比如说,你的DAO Bean实例化之前你必须要先实例化Database Bean,DAO Bean并不需要持有一个Database Bean的实例。因为DAO的使用是依赖Database启动的,如果Database Bean不启动,那么DAO即使实例化也是不可用的。这种情况DAO对Database的依赖是不直接的。

除了在DAO上使用构造函数注入Database Bean以外,Spring没有任何依赖注入的关系能够满足上面的情况。但是DAO也许根本不需要Database的实例被注入,因为DAO是通过JDBC访问数据库的,它不需要调用Database 上的任何方法和属性。

通过定义depends-on=”database”可以控制Sping实例化dao的顺序。在任何时候Spring总会保证实例化DAO之前先实例Database。
    通常depends-on常常应用在上面的场景中。`如果DAO depend-on Database的同时需要得到Database的实例,那么使用构造函数注入是一个比较好的解决办法。`因为构造函数注入的方式是要先实例化目标对象依赖的对象然后在实例化目标对象。


>演示代码

```java
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
4    "http://www.springframework.org/dtd/spring-beans.dtd">
5 <beans>
6   <bean name="dao" class="research.spring.beanfactory.ch3.Dao" depends-on="database">
7   </bean>
8   <bean id="database" class="research.spring.beanfactory.ch3.Database">
9   </bean>   
10 </beans>

```

> 注意事项

sping中不允许循环引用 A depends-on B ,B depends-on A。
但是允许 连续的提前初始化 A depends-on B ,B depends-on C


# 2 bean的作用域
bean的作用域分为四块,`经常使用的是singleton和prototype作用域`。
当声明一个bean的时候就需要指定bean的作用域,不同的作用域存在巨大的差异,`默认是singleton`。
> singleton : 在spring ioc容器之中只会有一个bean实例,bean以单例为主存在。


> prototype :每次使用的时候都会返回一个新的bean实例,相当于每次调用getBean() 时,都调用了new Bean() 方法。

> request : 顾名思义和请求有关,每次请求都会创建一个新的bean。

> session : 顾名思义和session有关,相同的一个session下返回相同的bean,不同的session下返回不同的bean实例

> global-session : global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。


![请添加图片描述](https://img-blog.csdnimg.cn/7552b0d59a3d4235b398146002ad28bf.png)



# 3 lazy-init 懒加载
`ApplicationContext 默认会将所有属性为singleton bean在启动时全部加载到容器中`,这样做的`好处是我们在使用的时候会快速响应`,但是启动的时候需要加载过多的东西,`可能会导致启动时间较长`。
同时`还有一个好处,就是在启动的时候我们可以发现那些属性在装配的时候可能会出现的问题,如果在使用的时候再去加载,可能两三天我们才会发现这个问题。`

对于一些体积较大,使用较少的bean我们可以通过lazy-init让它在被调用的时候再去加载,是很好的提升启动性能的方式。
`spring实现lazy-init的方法有很多,比如再sping中有一个注册表,类似与map集合,有key和value
value就是bean。sping通过先创建响应的key,当key真正被调用的时候,调用new bean() 来创建响应的对象。`

lazy-init懒加载 是`在该类第一次被调用的时候加载`,如果其它的singleton bean内引用了懒加载的bean。那么在applicationContext的时候两个bean都会被加载。因为sigleton bean在启动时会被加载,而它引用了我们的lazy-init bean,lazy-init bean在第一次被调用的时候加载,也就成了applicationContext启动的时候加载了。

# 4 Autowrite和Resource的区别和使用
@Autowrite()和@Resource都是用来注入对象的,最大的区别就是Autowrite默认按照类型来匹配而Resource默认按照name(bean的id)来匹配。

Resource有两个重要属性,一个是type,一个是name。spring把name属性对象了bean的name(id)。把type对应了bean的type(一般就是我们的类名)。
当@Resource中同时指定了name和type,spring会同时匹配查找对应的bean,找不到则抛出异常。
当@Resource指定了type,则按照type去查找指定的bean,找不到或者找到多个都会抛出异常。
当@Resource指定了name,则按照name查找,找不到则抛出异常。
当@Resource都没有指定,则先按照name进行匹配,如果使用在变量上,一般将变量名作为name查找。如果作用在set()方法上,则会使用属性名作为name。 如果没有匹配上,则退回使用type再进行匹配

@Autowrite则默认按照类型进行匹配,也可以作用再变量和set方法上。默认情况下要求bean必须存在,如果要允许null值,可以设置require=false。

qwerdf4567 发表于 2023-1-4 15:15

路过打卡

mao3661280 发表于 2023-1-4 15:44

路过打啦

刘样andholiday 发表于 2023-1-4 16:10

Autowrite自动装配yyds
页: [1]
查看完整版本: spring提前加载,懒加载,bean的作用域和注入注解讲解