Spring IOC(控制反转)与依赖注入(DI)

控制反转:

  1. 控制:Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。简单来讲,由谁来控制对象的创建,传统应用程序的对象是由有程序本身控制创建的(直接new一个对象 ),使用Spring之后,对象由Spring创建(放在容器里管理)
  2. 反转:程序本身不创建对象,而是编程被动的接收对象,通过new ClassPathApplicationContext(配置文件位置)获取Spring上下文context,作为IoC容器入口,然后就可以从容器中获取想要的bean,context.getBean(beanID)。何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

依赖注入(DI)

也就是Dependency Injection,实现依赖注入的三种方式:
1.通过构造方法实现:将依赖对象由构造方法的参数传入
2.通过setter方法实现:为每个依赖对象提供一个set方法
3.通过接口的方式实现(已经被废弃)

通过构造方法实现

在bean标签内部使用 constructor-arg标签
type属性:使用类型指定构造方法中参数的类型
index属性:使用构造方法中参数索引值来 进行注入
name属性 :使用构造方法中参数名称 来注入 ( 常用!)
value属性:要注入的值(基本数据类型和String类型)
ref属性:要注入的值(引用在IOC容器中其他的bean对象)
优点:创建时必须要指定构造方法中的全部参数,bean才能被创建,保证了对象创建出来之后,成员变量一定都有值
缺点:必须要指定全部参数,否则无法创建,使用该方式改变了对象的创建过程
例子:
假设有一个构造器

public Student(String name,int age,Teacher teacher){
       this.name=name;
       this.age=age;
       this.teacher=teacher;
}
<bean id="studentBean" class="pojo.Student">
    <!--给构造器的第一个参数赋值。index从0开始-->
    <constructor-arg index="0" value="张三"/>
    <!--给构造器的第二个参数赋值。name:参数名,value:参数值-->
    <constructor-arg name="age" value="18"/>
    <!--给构造器的第三个参数赋值。引用在IOC容器中其他的bean对象-->
    <constructor-arg name="teacher" ref="teacherBean"/>
</bean>
<bean id="teacherBean" class="pojo.Teacher">
...
</bean>
通过setter方法实现

为每个注入的属性提供一个set方法,也就是说,底层其实是通过setter方法给属性赋值的
比如:

private String name;  
//然后有一个setter方法
public void setName(String name){
       this.name=name;
}

实际上,不一定要有private String name,没有这个属性依旧能完成属性的注入,前提是有public void setName(String name)方法,也就是说,在依赖属性注入里面,属性是指setter方法去掉set,然后开头变小写的那个名。例如setName===>name,而不是上面显示声明的属性。
下面是各种类型的属性注入方式:

private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String, String> card;
private Set<String> games;
private String wife2;
private Properties info;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="address" class="com.pojo.Address">
        <property name="address" value="BeiJing"/>
    </bean>

    <bean id="student" class="com.pojo.Student">
        <!--基本数据类型herString注入-->
        <property name="name" value="YuJing"/>
        <!--引用类型注入-->
        <property name="address" ref="address"/>
        <!--数组类型注入-->
        <property name="books">
            <array value-type="java.lang.String">
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>
        <!--单列集合List注入-->
        <property name="hobbies">
            <list value-type="java.lang.String">
                <value>看综艺</value>
                <value>敲代码</value>
                <value>听歌</value>
            </list>
        </property>
        <!--双列结合Map注入-->
        <property name="card">
            <map key-type="java.lang.String" value-type="java.lang.String">
                <entry key="YuJing" value="123456"/>
                <entry key="JingYu" value="654321"/>
            </map>
        </property>
        <!--单列结合Set-->
        <property name="games">
            <set value-type="java.lang.String">
                <value>LOL</value>
                <value>COC</value>
                <value>BOB</value>
            </set>
        </property>
        <!--空值null-->
        <property name="wife1">
            <null/>
        </property>
        <!--空字符串注入-->
        <property name="wife2" value=""/>
        <!--Properties注入-->
        <property name="info">
            <props>
                <prop key="driver">com.mysql.jdbc.driver</prop>
                <prop key="url">http://mysql</prop>
                <prop key="username">root</prop>
                <prop key="password">root</prop>
            </props>
        </property>
    </bean>
</beans>
通过接口的方式实现(已经被废弃)
c命名空间和p命名空间

为了简化上述两种配置方式,Spring为我们提供了与上述两种方式分别对应的扩展方式:
c命名空间:也就是constructor构造器,简化通过构造方法实现,需要在配置文件中加入约束

xmlns:c="http://www.springframework.org/schema/c" 

前提是你要有对应的构造器,才能实现对应的注入,之后可以简写成:
例如:

public Student(String name,Teacher teacher){
			this.name=name;
			this.teacher=teacher;
}
<bean id="studentBean" class="pojo.Student" c:name="张三" c:teacher="teacherBean">
</bean>
<bean id="teacherBean" class="pojo.Teacher">
...
</bean>

p命名空间:也就是property属性,简化通过setter方法实现,需要再配置文件中加入约束

xmlns:p="http://www.springframework.org/schema/p"

前提是你要有对应的setter方法,才能实现对应的注入,之后可以简写成:

<bean id="studentBean" class="pojo.Student" p:name="张三" p:age="18" p:teacher="teacherBean">
</bean>
<bean id="teacherBean" class="pojo.Teacher">
...
</bean>

上面两个看上去没有什么区别,但第一个实际上是通过构造器注入的,第二个是通过setter方法注入的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子酷兒233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值