Spring框架 -- 3 Spring中的DI介绍

Spring中的DI介绍

  • 基于配置的形式注入依赖
    • 有参构造函数注入依赖
    • set方法注入依赖
  • 基于注解的形式注入依赖
    • @Value注解
    • @Resource注解
    • @Autowired注解
  • 依赖解析过程

DI-Dependency Injection,即“依赖注入”,组件之间的依赖关系由容器在运行期决定,即容器动态的将某个依赖关系注入到组件当中。

DI理解的关键点:“谁依赖谁,为什么需要依赖”
谁依赖谁:应用程序依赖IOC容器
为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源
注入什么:注入某个对象所依赖的外部资源

基于配置的形式注入依赖

有参构造函数注入依赖

    <!--依赖注入方式1:有参构造-->
    <bean id="user3" class="com.tulun.bean.User">
        <!--id属性的注入-->
        <constructor-arg name="id" value="22"></constructor-arg>
        <!--name属性的注入-->
        <constructor-arg name="name" value="zhangsan"></constructor-arg>
    </bean>

有参构造函数的依赖注入主要使用标签 name属性:表示类中的属性名 value属性:当前属性名赋值
在类中必须包含有参构造函数,且和构造函数保持参数一致
Spring框架 -- 3 Spring中的DI介绍_第1张图片

set方法注入依赖

    <!--依赖注入方式2:set方法-->
    <bean id="user4" class="com.tulun.bean.User">
        <!--id属性注入-->
        <property name="id" value="12"/>
        <!--name属性赋值-->
        <property name="name" value="李四"/>
    </bean>

set方法注入依赖时,使用property标签,name属性表示类中的属性名,value属性表示当前属性的赋值
Spring框架 -- 3 Spring中的DI介绍_第2张图片

注入的属性可以是基本的类型,也可以是集合类型,也可以是自定义类型

<!--对象的注入-->
    <!--在Person类中注入自定义的User-->
    <bean id="user5" class="com.tulun.bean.User"/>
    <bean id="person" class="com.tulun.bean.Person">
        <!--user属性通过set方式注入-->
        <!--value:会按照String类型的字符串做解析   ref:Spring中管理对象的ID名-->
        <property name="user" ref="user5"/>
    </bean>

集合类型
注入List类型的

    <!--List的注入-->
    <bean id="person1" class="com.tulun.bean.Person">
        <property name="list">
            <list>
                <value>hello</value>
                <value>你好</value>
                <value>123</value>
            </list>
        </property>
    </bean>

其他形式的集合配置

 <!--数组的注入-->
    <bean id="person2" class="com.tulun.bean.Person">
        <property name="list">
            <!--array标签:注入数字-->
            <array>
                <!--value是直接给定值-->
                <value></value>
                <!--ref是存储的引用对象-->
                <!--<ref></ref>-->
            </array>
        </property>
    </bean>

    <!--set的注入-->
    <bean id="person3" class="com.tulun.bean.Person">
        <property name="list">
            <!--set标签:注入set类型的集合-->
            <set>
                
            </set>
        </property>
    </bean>

    <!--map的注入-->
    <bean id="person4" class="com.tulun.bean.Person">
        <property name="list">
            <!--map标签:注入Map类型的集合-->
            <map>
                <entry key="1" value="zhangsan"/>
            </map> 
        </property>
    </bean>

基于注解的形式注入依赖

  • @Value:注入普通形式的依赖
  • @Resource:注入对象类型
  • @Autowired:注入对象类型

@Value注解

@Component(value = "user")
public class User {
     
    @Value("1")
    private String id;
    
    @Value("张三")
    private String name;

注:使用Value注解注入依赖前提是Bean的装配支持注解扫描

@Component(value = "person")
public class Person {
     
    //自定义类型属性
    //和@Resource功能一样
    @Autowired
    private User user;
}

@Resource注解

@Autowired注解

@Resource和@Autowired的异同点?

在Spring中,@Resource和@Autowired都是做Bean的注入时使用,@Resource和@Autowired可以替换使用。

相同点:
@Resource和@Autowired是可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解效果一样,可互相替换,不影响使用。

不同点:
@Resource 是Java中提供的注解,@Resource存在两个属性,分别为name和type,在Spring中是通过name来解析bean的名字,而type属性则解析为bean的类型。所以如果使用name属性时,使用byName自动注入策略,而使用type属性时则使用byType自动注入策略,如果不指定name或者type属性时,这时将通过反射机制使用byName自动注入策略

@Autowired 是Spring提供的注解,在Spring2.5版本引入,@Autowired只根据type进行注入,不会去匹配name,如果type无法识别注入对象时,需要依赖@Qualifiler或者是Primary注解一起修饰

依赖解析过程

容器解析Bean的依赖过程:

  • ApplicationContext是通过配置元数据来创建初始化的,这些元数据描述了所有的bean,描述元数据可以通过XML,注解或者Java代码来指定。
  • 对于每一个bean,它的依赖注解,构造方法参数或者静态工厂参数的形式来表达。bean在被创建好之后这些依赖会被提供给他。
  • 每一个属性或者构造方法的参数都要设定的值的实际定义,或者对容器内另一个bean的引用。

容器在创建的时候,Spring容器会验证每一个bean的信息,在实际创建bean之前,bean的属性是不会被设置的。bean只会在需要他的时候被创建,创建bean的过程中可能会引起一系列的bean被创建,例如bean的依赖,其依赖的依赖等等会被一起创建和分配。注意:依赖之间解析不匹配可能会出现,即首循环创建有影响的bean。

循环依赖的问题

class User{
     
	private Person person;
}

class Person{
     
	private User user;
}

如果是通过构造方法的方式注入,就有可能造成无法解决的循环依赖

例如:ClassA需要通过构造方法注入一个ClassB的实例,ClassB同样需要通过构造方法注入ClassA的实例,如果为ClassA和ClassB配置bean并且相互注入,IOC容器在运行时会发现这个循环引用,抛出异常:BeanCurrentlyInCreationException

解决循环依赖的途径需要去编辑代码,让这些类通过setter方法注入,避免使用构造方法注入。

你可能感兴趣的:(spring,java)