首页 > 代码库 > Spring基础入门之IoC注入

Spring基础入门之IoC注入

我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由多个对象组成的,所有的对象通过彼此之间的合作,最终实现系统的业务逻辑,为了解决对象之间的耦合度过高的问题,Spring的IOC理论,用来实现对象之间的“解耦”.IOC的中文意思就是“控制反转”,通俗的理解成权利反转,本来对象的创建由程序员自己写new的代码,new出一个类的对象,在调用它的方法,当代码项目一多起来,就暴露了一个问题:要new的类越多越不好管理。于是Spring的IoC就是把创建对象的事情放在Spring容器里面;就是把东西甩给了容器做,而不再是程序员一个一个new .

Spring的依赖注入可以用手工装配或自动装配.

下面先介绍经常使用的手动装配方式

手动装配方式主要有三种:(1)set方法注入(2)构造方法注入(3)工厂方法注入  (Spring不支持接口注入)

1.Set注入方式,属性

通过无参构造函数set方法注入,这种方式必须提供一个set方法,否则会报异常

①先定义一个emp类;写上对一个的get set方法;

public emp{
private Integer id;

public emp(){}
set方法;
get方法;

}

 

②定义一个接口EmpService 和Empdao接口empservice是emp的service类,empdao是epm的数据库操作类;

public interface EmpService {
    void save(Object o);
    void delete(Integer id);}}

public interface EmpDao {
    void del(Integer id);
    void add();
}

③EmpserviceEmpDao的实现类

 

public class EmpServiceImpl implements EmpService {
    private EmpDao dao;
    public EmpServiceImpl() {
    }
    public void save(Object o) {
            System.out.println("保存了员工");
    }
    public void delete(Integer id) {
        dao.del(id);
        System.out.println("删除了员工"+id);
    }
    public EmpServiceImpl(EmpDao dao) {
        super();
        this.dao = dao;
    }
    public EmpDao getDao() {
        return dao;
    }
    public void setDao(EmpDao dao) {
        this.dao = dao;
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

 

 

public class EmpDaoService implements EmpDao {

    public EmpDaoService() {
    }
    @Override
    public void del(Integer id) {
        System.out.println("删除了员工");
    }

 

④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="EmpServiceImplid" class="com.an.service.EmpServiceImpl" >
<property name="Dao" ref="EmpDaoServiceid" /></bean>
<bean id="EmpDaoServiceid" class="com.an.service.EmpDaoService" ></bean>
</beans>

<bean>中的id用来做标识,标志这哪一个类;

class需要创建的类的全名, <property>标签中的name就是EmpDaoService中的Dao属性名,前提是EmpDaoService必须去提供一个set方法让spring把值传进去,因为name的内容不是根据变量名(属性),是根据set方法生成的ref指的是引用另一个bean,在这里就是指向下面<bean id="EmpDaoServiceid"…/>

 

⑤编写测试类测试结果

 

public class EmpServiceTest {

    public EmpServiceTest() {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args) {

        //创建Spirng的工厂
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取Empservice
        EmpService serv=(EmpService) ac.getBean("EmpServiceImplid");
        //
        serv.delete(1);
        
    }

 

运行结果:

删除了员工

删除了员工1

set注入的缺点是无法清晰表达哪些属性是必须的,哪些是可选的,构造注入的优势是通过构造强制依赖关系,不可能实例化不完全的或无法使用的bean

 

2.带参数的构造方法注入

 

这种方式的注入是指带有参数的构造函数注入,下面的例子,创建了两个成员变量idname,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在emp的构造函数中注入,也就是说在创建emp对象时要将id,namer两个参数值传进来。

①emp类的编写如下:

 

public class emp {
    private String name;
    private int id;
    public emp() {
        // TODO Auto-generated constructor stub
    }
    public emp(String name, int id) {
        super();
        this.name = name;
        this.id = id;
System.out.println("调用了构造方法 "+name+id);
    }

    

}

 

 

 

 

②xml的配置文件修改如下:

 

<bean class="com.an.service.emp" id="emp">
    <constructor-arg name="id" value="http://www.mamicode.com/1101"></constructor-arg>
    <constructor-arg name="name" value="http://www.mamicode.com/Anre"></constructor-arg>
</bean>

 

③测试类

public class testemp {
    public testemp() {
    }
    public static void main(String[] args) {
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        emp e=ac.getBean("emp",emp.class);
    }
}

④运行结果:

 

 

调用了构造方法 Anre1101

 

另外几种通过构造方法注入的方式构造注入特别是针对有些属性需要在对象在创建时候赋值,且后续不允许修改(不提供setter方法)

 

 

1)根据索引(2)根据数据类型(3)直接赋值

 

 

1) 根据索引注入根据索引赋值,索引都是以0开头的:

<constructor-arg index="0" value="http://www.mamicode.com/1101" />

<constructor-arg index="1" value="http://www.mamicode.com/anso" />

 

 (2)根据数据类型注入

这种方法基本上不怎么适用,个类里可以有好几个相同基本类型的变量,很容易就混淆值传给哪一个参数了

<constructor-arg index=”Java.lang.Integer” value="http://www.mamicode.com/1101" />

<constructor-arg type=”Java.lang.String” value="http://www.mamicode.com/anso" />

 

 

 (3)直接赋值注入

通常不推荐使用直接给参数赋值,这种方法根据参数的顺序传入的参数位置不对,就会出现问题

<constructor-arg  value="http://www.mamicode.com/1101" />

<constructor-arg  value="http://www.mamicode.com/anso" />

 

通过Spring创建的对象默认是单例的,如果需要创建多实例对象可以在<bean>标签后面添加一个属性:

<bean name="..." class="..." scope="prototype">

 

<bean>标签中,加上scope属性来控制对象在容器中的数量
(1)scope = singlton (单例模式),对象在容器中全局唯一,在IOC容器初始化的时候该对象就会被创建
(2)scope = prototype (多例模式),在每一次调用getBean的时候IOC容器才会创建该对象的实体,并且每次创建都是不同的对象

 

Spring基础入门之IoC注入