① IoC的直译是控制反转。 在IoC模式下,控制权限从应用程序转移到了IoC容器中。组件不是由应用程序负责创建和配置,而是由IoC容器负责。 使用IoC的情况下,对象是被动地接收依赖类而不是主动地查找。对象不是从容器中查找他的依赖类,而是容器在实例化对象时,主动地将他所依赖的对象注入给他。 应用程序只需要直接使用已经创建并且配置好的组件即可,而不必自己负责创建和配置。 在实际的工作中人们发现使用IoC来表述这种机制,并不是很准确甚至有些晦涩,于是引发了另外一个概念:DI(依赖注入)
② DI解析 之所以会产生组件调用,是为了获取被调用组件的功能,调用者将自己应该做的事情,委派给了被调用的对象。也就是说,调用者要完成自身的任务,必须依赖被调用的对象。这种关系实际上就是一般依赖关系(通俗点说,就是一个组件内部包含另外一个组件的实例,把该自己干的事交给自己包含的组件去完成)。因此IoC所表述的机制,实际上就是将调用者对接口实现类的依赖关系,从程序中移除,转交第三方管理实例。并且,由第三方在运行期间将调用者依赖的具体类填充进来。也就是说组件之间的依赖关系,是在程序运行期间由第三方来管理的。这个就是依赖注入的概念(DI),基于上述分析,DI比IoC更准确。
实际上就是将调用者为完成功能所依赖的实现类,在程序运行期间,由容器自动填充给调用者,这个就是依赖注入的核心思想。在依赖注入的应用中,组件并不关心被注入的对象是谁,只关系这个对象能完成的功能,也就是这个对象是哪个接口的具体类实例。
ApplicationContext.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-4.1.xsd"> <!-- 构造函数注入:constructor-arg index:可省略,构造函数参数的下标,从0开始 name:可省略,构造函数参数的名称,例如:public UserService(IUserDao userDao,String userName) userDao与userName ref:表示在容器中需要引用的bean的ID的属性值 value:给基本属性数据类型或String赋值 注意: 1、参数个数必须一致 2、两边参数的类型必须一致 3、建议保留默认的无参构造函数 4、建议不要省略name --> <bean id="userService" class="spring.UserService"> <constructor-arg index=0 name="userDao" ref="userDao"></constructor-arg> <constructor-arg index=1 name="userName" value="给基础类型赋值"></constructor-arg> </bean> <bean id="userDao" class="spring.UserDaoImpl"></bean> </beans>UserService:
package spring; public class UserService { private IUserDao userDao; private String userName; //无参构造函数 public UserService() { System.out.println("new UserService() 实例化"); } //有参构造函数 public UserService(IUserDao userDao,String userName) { this.userDao = userDao; this.userName=userName; } public void findUsers() { userDao.selectUser(); } }测试类:
public static void main(String[] args) { //加载并解析ApplicationContext.xml ClassPathXmlApplicationContext factory= new ClassPathXmlApplicationContext("applicationContext.xml"); //获取工厂中的IUseDao对象 IUserDao userDao= (IUserDao)factory.getBean("userDao"); //调用方法 userDao.selectUser(); //销毁对象 factory.close(); }set属性注入: UserService:
package spring; public class UserService { private IUserDao userDao; private String userName; public void setUserDao(IUserDao userDao) { this.userDao = userDao; } public void setUserName(String userName) { this.userName = userName; } public void findUsers() { userDao.selectUser(); } }ApplicationContext.xml:
<!-- set属性注入:property name:必须为set方法后面的属性值,例如:public void setUserDao(IUserDao userDao),name值为set后面的UserDao,都是首字母必须小写即为userDao ref:表示在容器中需要引用的bean的ID的属性值 value:给基本属性数据类型或String赋值 平时调用时的使用: UserService userService = new UserService(); userService.setUserDao(userDao); userService.setUserName(userName); --> <bean id="userService" class="spring.UserService"> <property name="userDao" ref="userDao"></property> <property name="userName" value="李四"></property> </bean> <bean id="userDao" class="spring.UserDaoImpl"></bean>其实还有一种注入方式:接口注入(Spring不支持)
这两种方式是原生的:手动装配,非注解方法注入,后面会讲到,手动方式装配,注解方式注入和自动装配