Spring的核心机制就是Ioc(控制反转)容器,IoC的另外一个称呼就是依赖注入(DI),通过依赖注入,JavaEE应用中的各种组件不需要以硬编码的方法进行耦合,当一个Java实例需要其他Java实例的时候,系统自动提供需要的实例,无需程序显示的获取,因此,依赖注入实现了组件之间的解耦;
1>理解控制反转
依赖注入和控制反转含义相同,当某个Java实例需要另外一个java实例时,传统的方法是由调用者来创建被调用者的实例,例如使用new关键字获取被调用者的实例;
采用依赖注入方式时,被调用者的实例不再需要由调用者来创建,成为控制反转,被调用者的实例通常是由Spring容器来完成,然后注入调用者,调用者便获得了被调用者的实例,称为依赖注入;
2>如何使用Spring的依赖注入
Spring提倡面向接口编程,依赖注入的基本思想是:明确的定义组件的接口,独立开发各个组件,然后根据组件的依赖关系组装运行;
3>示例:(登录)
1>>添加依赖的jar文件,包括commons-logging-1.2.jar;
2>>编写DAO层
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>package com.shw.dao;
public interface UserDAO {
public boolean login(String username, String password);
}
</strong></span>
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>package com.shw.dao;
public class UserDAOImpl implements UserDAO {
@Override
public boolean login(String username, String password) {
if(username.equals("admin") && password.equals("123456")){
return true;
}
return false;
}
}
</strong></span>
3>>编写Biz层
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>package com.shw.biz;
public interface UserBiz {
public boolean login(String username, String password);
}
</strong></span>
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>package com.shw.biz;
import com.shw.dao.UserDAO;
public class UserBizImpl implements UserBiz {
// 使用UserDAO接口声明一个对象
// 并为其添加set方法,用于依赖注入
UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
@Override
public boolean login(String username, String password) {
return userDAO.login(username, password);
}
}
</strong></span>
在上述代码中,没有采用传统的方法,即通过new UserDAOImpl()方式获取数据访问层UserDAOImpl类的实例,而是通过UserDAO接口声明了一个对象userDAO,并为其添加set方法,用于依赖注入;
UserDAOImpl类的实例化和对象userDAO的注入将在applicationContext.xml配置文件中完成;
4>>配置applicationContext.xml文件
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong><?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">
<!-- 配置创建UserDAOImpl的实例 -->
<bean id="userDAO" class="com.shw.dao.UserDAOImpl"></bean>
<!-- 配置创建UserBizImpl的实例 -->
<bean id="userBiz" class="com.shw.biz.UserBizImpl">
<!-- 依赖注入数据访问层组件 -->
<property name="userDAO" ref="userDAO"></property>
</bean>
</beans></strong></span>
<bean>标记用来定义Bean的实例化信息,calss属性指定类全名(包名+类名),id属性指定生成的Bean的名称,上述配置中,首先通过一个<bean>标记创建了UserDAOImpl类的实例,再使用另一个<bean>标记创建UserBizImpl类的实例时,使用了<property>标记,该标记是<bean>标记的子标记,用于调用Bean实例中的相关Set方法完成属性的赋值,从而实现依赖关系的注入。
<property>标记中的name属性指定Bean实例中的相应属性的名称,这里name属性设置为userDAO,代表UserBizImpl类中的userDAO属性需要赋值,name属性的值可以通过ref属性或者value属性指定,当使用ref属性时,表示对Bean工厂中某个Bean实例的引用,这里引用了第一个<bean>标记创建的UserDAOImpl类的实例,userDAO,并将该实例赋值给UserBizImpl类的userDAO属性,从而实现了依赖关系的注入;
UserBizImpl类的userDAO属性值是通过调用setUserDAO()方法注入的,这种注入方式成为设值注入,设值注入方式是Spring推荐使用的;
5>>测试:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.shw.biz.UserBiz;
public class Test {
public static void main(String[] args) {
//加载applicationContext.xml配置
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取配置中UserBizImpl实例
UserBiz userBiz = (UserBiz)context.getBean("userBiz");
//UserBizImpl userBiz = (UserBizImpl)context.getBean("userBiz");
System.out.println(userBiz.login("admin", "123456"));
}
}
</strong></span>
注:
在UserBizImpl中的属性userDAO属性,属性名字随便起,给这个属性的set方法可以除了set这三个字母存在,方法名称随便定义,比如setXXX(),参数名称也随便定义,只要保证两点:
1>有set这个字眼
2>将参数赋值给上面的属性
关键在于applicationContext.xml这个文件进行配置要与之对应,
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong><property name="userDAO" ref="userDAO"></property></strong></span>
这个ref要与上面配置的类的bean的id一致,保证赋值是赋的这个类,name属性与setXXX的XXX完全一样(除了第一个字母,set后面的第一个字母是大写的);
这个赋值的含义就是把ref指定的id的那个类当作参数,去寻找set+name属性的那个set方法,将这个参数传进去赋值给指定的属性;
所有名字都可以随便起,只要保证这两个地方一致即可:
1>ref和<bean>的id一致;
2>name和set方法的后半个名字一样即可;(set方法后的第一个字母大小写问题)