Spring依赖注入、IOC容器

spring的依赖注入:通过spring的ioc容器来管理对象的生命周期。在spring中,可以通过注解、xml配置的方式使用依赖注入功能。

一、注解方式

spring中,提供了Service,Controller,Repository,Component注解用来修饰类,标记这些类要生成bean,交给ioc容器来管理。同时提供了Autowired和Resource注解用来修饰字段,构造函数,或者set方法,用来标识依赖注入关系。

1、dao层接口和实现类:

1
2
3
public interface DemoDao {
public List<Map> query() ;
}

实现类:注解放到实现类上

1
2
3
4
5
6
7
8
9
10
11
@Repository
public class DemoDaoImpl implements DemoDao{
public List<Map> query() {
List<Map> list = new ArrayList<Map>();
Map map = new HashMap();
map.put("id", "1");
map.put("name", "liuxiao");
list.add(map);
return list;
}
}

2、service层接口、服务器:

1
2
3
public interface DemoService {
public void sayHello(String name) ;
}

实现类:注解放到实现类上

1
2
3
4
5
6
7
8
9
10
@Service  
public class DemoServiceImpl implements DemoService{
@Autowired
private DemoDaoImpl demoDao;

public void sayHello(String name) {
System.out.println(demoDao.query());
System.out.println("hello word.........."+name);
}
}

3、测试:
1)使用AnnotationConfigApplicationContext

1
2
3
4
5
6
7
8
public class App  {
public static void main( String[] args ) {
ApplicationContext appContext = new AnnotationConfigApplicationContext("cn.edu.nuc.SpringTest");
//DemoServiceImpl ser = (DemoServiceImpl) appContext.getBean("demoServiceImpl");
DemoServiceImpl ser = appContext.getBean(DemoServiceImpl.class);
ser.sayHello("刘晓");
}
}

2)使用ClassPathXmlApplicationContext
A、配置application.xml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 自动扫描-->
<context:component-scan base-package="cn.edu.nuc.SpringTest"/>
<!-- 注解方式的aop
<aop:aspectj-autoproxy proxy-target-class="true"/>-->
</beans>

B、测试类
1
2
3
4
5
6
7
8
9
10
11
public class App  {
public static void main( String[] args ) {
String[] fileUrl = new String[]{"classpath*:applicationContext.xml"};
ApplicationContext appContext = new ClassPathXmlApplicationContext(fileUrl);


//DemoServiceImpl ser = (DemoServiceImpl) appContext.getBean("demoServiceImpl");
DemoServiceImpl ser = appContext.getBean(DemoServiceImpl.class);
ser.sayHello("刘晓");
}
}

注:

  • 通过AnnotationConfigApplicationContext初始化applicationContext对象,指定要扫描的包路径即可,不需要任何配置文件。
  • 通过ClassPathXmlApplicationContext构造ApplicationContext对象,指定xml配置文件的位置即可。
  • 获取bean时可以通过type和name两种方式。

二、xml配置文件的方式

不需要在类、变量上面写注解,直接把bean的信息和依赖信息配置到配置文件中。这里需要提一下spring的四中依赖注入:

1、set注入:
最简单的,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是ioc的注入入口):

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.bless.springdemo.action;  
public class SpringAction {  
    //注入对象springDao  
    private SpringDao springDao;  
     //一定要写被注入对象的set方法  
    public void setSpringDao(SpringDao springDao) {  
        this.springDao = springDao;  
    }  
  
    public void ok(){  
        springDao.ok();  
    }  
}

配置文件:

1
2
3
4
5
6
7
<!--配置bean,配置后该类由spring管理-->  
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(1)依赖注入,配置当前类中相应的属性-->  
        <property name="springDao" ref="springDao"></property>  
</bean>  

<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>

2、构造方法注入:指带有参数的构造函数注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SpringAction {  
    //注入对象springDao  
    private SpringDao springDao;  
    private User user;  
      
    public SpringAction(SpringDao springDao,User user){  
        this.springDao = springDao;  
        this.user = user;  
        System.out.println("构造方法调用springDao和user");  
    }  
          
        public void save(){  
        user.setName("卡卡");  
        springDao.save(user);  
    }  
}

配置文件:

1
2
3
4
5
6
7
8
<!--配置bean,配置后该类由spring管理-->  
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->  
        <constructor-arg ref="springDao"></constructor-arg>  
        <constructor-arg ref="user"></constructor-arg>  
 </bean>  
 <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  
<bean name="user" class="com.bless.springdemo.vo.User"></bean>

注:解决构造方法参数的不确定性,你可能会遇到构造方法传入的两参数都是同类型的,为了分清哪个该赋对应值,则需要进行一些小处理:
1)使用index:

1
2
3
4
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
<constructor-arg index="0" ref="springDao"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>

2)使用类型:

1
<constructor-arg type="java.lang.String" ref=""/>

3、静态工厂的方法注入:
静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有对象,我们不能直接通过”工程类.静态方法()”来获取对象,而是依然通过spring注入的形式获取:

1
2
3
4
5
6
7
8
9
10
11
12
package com.bless.springdemo.factory;  
  
import com.bless.springdemo.dao.FactoryDao;  
import com.bless.springdemo.dao.impl.FactoryDaoImpl;  
import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl;  
  
public class DaoFactory {  
    //静态工厂  
    public static final FactoryDao getStaticFactoryDaoImpl(){  
        return new StaticFacotryDaoImpl();  
    }  
}

同样看关键类,这里我需要注入一个FactoryDao对象,这里看起来跟第一种注入一模一样,但是看随后的xml会发现有很大差别:
1
2
3
4
5
6
7
8
9
10
11
12
public class SpringAction {  
        //注入对象  
    private FactoryDao staticFactoryDao;  
      
    public void staticFactoryOk(){  
        staticFactoryDao.saveFactory();  
    }  
    //注入对象的set方法  
    public void setStaticFactoryDao(FactoryDao staticFactoryDao) {  
        this.staticFactoryDao = staticFactoryDao;  
    }  
}

Spring的IOC配置文件,注意看指向的class并不是FactoryDao的实现类,而是指向静态工厂DaoFactory,并且配置 factory-method=”getStaticFactoryDaoImpl”指定调用哪个工厂方法:
1
2
3
4
5
6
7
<!--配置bean,配置后该类由spring管理-->  
<bean name="springAction" class="com.bless.springdemo.action.SpringAction" >  
        <!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->  
        <property name="staticFactoryDao" ref="staticFactoryDao"></property>  
 </bean>  
    <!--(3)此处获取对象的方式是从工厂类中获取静态方法-->  
<bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>

4、实例工厂注入:
实例工厂的方法注入实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法:

1
2
3
4
5
6
public class DaoFactory {  
    //实例工厂  
    public FactoryDao getFactoryDaoImpl(){  
        return new FactoryDaoImpl();  
    }  
}

那么下面这个类没什么说的,跟前面也很相似,但是我们需要通过实例工厂类创建FactoryDao对象:
1
2
3
4
5
6
7
8
9
10
11
12
public class SpringAction {  
    //注入对象  
    private FactoryDao factoryDao;  
      
    public void factoryOk(){  
        factoryDao.saveFactory();  
    }  
  
    public void setFactoryDao(FactoryDao factoryDao) {  
        this.factoryDao = factoryDao;  
    }  
}

最后看spring配置文件:

1
2
3
4
5
6
7
8
9
10
<!--配置bean,配置后该类由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->  
        <property name="factoryDao" ref="factoryDao"></property>  
    </bean>  
      
    <!--(4)此处获取对象的方式是从工厂类中获取实例方法-->  
    <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>  

    <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>