spring入门学习第二篇

依赖注入IOC

IOC:inverse of control:控制反转

2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。

 

依赖注入:spring管理的bean,当它依赖一个被其他spring管理的bean的时候,spring负责把它注入进来

注入方式

1、构造函数注入(Constructor)

2、属性注入(setter)

3、接口注入(比较少用)

案例一:

EmpDao接口:

package com.complex;

public interface EmpDao {
    void insert();
}

EmpDaoImpl实现类:

package com.complex;

public class EmpDaoImpl implements EmpDao{

    @Override
    public void insert() {
        System.out.println("this is EmpDao Method insert");
    }
}

EmpService接口:

package com.complex;

public interface EmpService {
    void insert();
}

EmpServiceImpl实现类:

package com.complex;

public class EmpServiceImpl implements EmpService{
    private EmpDao empDao;

    public EmpServiceImpl(){}

    //构造函数注入
    public EmpServiceImpl(EmpDao empDao){ this.empDao = empDao;}

    @Override
    public void insert() {
        empDao.insert();
    }
}

xml:

<?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="empDaoImpl" class="com.complex.EmpDaoImpl"></bean>

    <bean id="empServiceImpl" class="com.complex.EmpServiceImpl">
        <!--可以看到我们通过构造函数注入,实现了在实例化bean的时候会将empDaoImpl这个bean自动注入到empServiceImpl这个bean的构造函数中实例化bean-->
        <constructor-arg ref="empDaoImpl"></constructor-arg>
    </bean>
</beans>

Main测试:

package com.complex;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_complex.xml");
        EmpServiceImpl empServiceImpl = context.getBean("empServiceImpl", EmpServiceImpl.class);
        empServiceImpl.insert();
    }

}

测试结果:this is EmpDao Method insert

我们通过依赖注入实现了在实例化Bean的时候通过构造函数注入EmpDao

为什么EmpServiceImpl放EmpDao接口类型,因为这样遵循依赖倒转原则:抽象不应该依赖于细节,细节应该依赖于抽象。

 

依赖注入详解

1、如何实现多个属性通过构造器注入

BookInfo类

package com.basic;

import java.math.BigDecimal;

public class BookInfo {
    private int id;
    private String name;
    private BigDecimal price;
    private int count;

    public BookInfo(int id, String name, BigDecimal price, int count) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.count = count;
    }
}

xml:

<?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="bookInfo" class="com.basic.BookInfo">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="童话故事"></constructor-arg>
        <constructor-arg name="price" value="15"></constructor-arg>
        <constructor-arg name="count" value="100"></constructor-arg>
    </bean>
</beans>
通过构造器注入我们可以指定构造参数,spring是如何知道要传的参数是哪个呢?

constructor-arg给我们提供了三种指定参数名的方法

name:设置参数名

index:设置参数索引

type:参数类型

如果不设置的话,spring会依据先后顺序一个个传参进去。

2、如何通过属性注入?

BookInfo类

package com.basic;

import java.math.BigDecimal;

public class BookInfo {
    private int id;
    private String name;
    private BigDecimal price;
    private int count;

    //get和set方法,这里省略了
}

xml

<?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="bookInfo" class="com.basic.BookInfo">
        <property name="id" value="1"></property>
        <property name="name" value="童话故事"></property>
        <property name="price" value="15"></property>
        <property name="count" value="100"></property>
    </bean>
</beans>

通过设置property实现属性注入,name指定对应的属性。

3、复杂类型如何注入?

前面我们实现的是简单的类型,那么问题来了,复杂类型如何注入?例如list,map,实体类等等

ShopCar

package com.basic;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class ShopCar {
    private String sname;   //基本类型
    private List<BookInfo> list;    //list集合
    private Map<Integer,BookInfo> map;  //map集合
    private Set<BookInfo> bookInfoSet;  //set集合
    private BookInfo bookInfo;  //实体对象

    public ShopCar(String sname, List<BookInfo> list, Map<Integer, BookInfo> map, Set<BookInfo> bookInfoSet, BookInfo bookInfo) {
        this.sname = sname;
        this.list = list;
        this.map = map;
        this.bookInfoSet = bookInfoSet;
        this.bookInfo = bookInfo;
    }
    
    //set和get方法,这里省略了....太长了
}

 

先来看看构造函数注入复杂类型

<?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="bookInfo" class="com.basic.BookInfo">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="童话故事"></constructor-arg>
        <constructor-arg name="price" value="15"></constructor-arg>
        <constructor-arg name="count" value="100"></constructor-arg>
    </bean>

    <bean id="shopCar" class="com.basic.ShopCar">
<!--        普通类型一样用value-->
        <constructor-arg name="sname" value="购物车1"></constructor-arg>
<!--        实体类用ref-->
        <constructor-arg name="bookInfo" ref="bookInfo"></constructor-arg>
<!--        list类型设置-->
        <constructor-arg name="list">
            <list>
                <ref bean="bookInfo"></ref>
                <bean class="com.basic.BookInfo">
                    <property name="id" value="2"></property>
                    <property name="name" value="小红帽"></property>
                    <property name="price" value="15"></property>
                    <property name="count" value="100"></property>
                </bean>
            </list>
        </constructor-arg>
<!--        map设置-->
        <constructor-arg name="map">
            <map>
                <entry key="1" value-ref="bookInfo"></entry>
            </map>
        </constructor-arg>
<!--        set设置-->
        <constructor-arg name="bookInfoSet">
            <set>
                <ref bean="bookInfo"></ref>
            </set>
        </constructor-arg>
    </bean>
</beans>

复杂类型属性注入

<?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="bookInfo" class="com.basic.BookInfo">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="童话故事"></constructor-arg>
        <constructor-arg name="price" value="15"></constructor-arg>
        <constructor-arg name="count" value="100"></constructor-arg>
    </bean>

    <bean id="shopCar" class="com.basic.ShopCar">
        <!--        基本类型-->
        <property name="sname" value="shop2"></property>
<!--        实体类型-->
        <property name="bookInfo" ref="bookInfo"></property>
<!--        list类型-->
        <property name="list">
            <list>
                <ref bean="bookInfo"></ref>
            </list>
        </property>
<!--        map类型-->
        <property name="map">
            <map>
                <entry key="1" value-ref="bookInfo"></entry>
            </map>
        </property>
<!--        set类型-->
        <property name="bookInfoSet">
            <set>
                <ref bean="bookInfo"></ref>
            </set>
        </property>
    </bean>
</beans>

结束!

 

 
posted @ 2019-10-18 11:49  过期可乐  阅读(203)  评论(1编辑  收藏  举报