“依赖注入”是spring的核心特征,在Web服务器(如Tomcat)加载时,它会根据Spring的配置文件中配置的bean或者是通过注解模式而扫描并装载的bean实例自动注入到ApplicationContext容器中(ApplicationContext容器管理了被注入的bean对象)。
下面做两个简单测试以说明spring“依赖注入“的两种模式:配置模式与注解模式。
测试工具:
一、新建spring配置文件,放在类目录下
在“src”上右键点"new",选择"Other”,搜索关键词"spring",选择Spring Bean Configuration File,点击"Next"
起个名字,点击“Finish”
建好的springTest.xml在类路径下,如下图所示:
二、.配置springTest.xml
首先,打开springTest.xml,如下所示--但这还不够,因为还需要一个xmlns:context="http://www.springframework.org/schema/context"作为配置环境,下面就开始配置吧。
<?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"> </beans>
a.配置xmlns:context="http://www.springframework.org/schema/context",见下图:
b.配置bean
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 将一个员工实例注入spring的ApplicationContext容器中。 --> <bean id="testEmpl" class="com.chen.vo.Empl"> <property name="ename" value="testName"></property> <property name="birthday" value="1999-01-01"></property> </bean> </beans>
现在,已经通过在springTest.xml中的配置将一个员工实例注入到ApplicationContext容器中了,下面将讲解怎样获取这个员工。
创建测试类SpringTest并编写getTestEmpl方法
@RunWith(SpringJUnit4ClassRunner.class)表示这是SpringJUnit4类型的测试类,而非单纯的JUnit4。
@ContextConfiguration("classpath:springTest.xml") 表示spring的配置文件路径。
FileSystemXmlApplicationContext是ApplicationContext 接口的一个实现类,它用来加载指定路径的spring配置文件。
classpath:springTest.xml表示类路径下的配置文件
package com.chen.test; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:springTest.xml") public class springTest { //获取ApplicationContext容器中的实例 @Test public void getTestEmpl(){ ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:springTest.xml"); //获取id为testEmpl的实例 System.out.println(applicationContext.getBean("testEmpl")); } }
打印信息如下:
Empl [eid=0, ename=testName, password=null, sex=null, birthday=1999-01-01, hiredate=null, admin=0, deptno=0, job=0, status=0, funs=null]
小结:通过以上的例子大致能了解到spring的“依赖注入”的这个核心特征,简单地说,我们通过在spring文件中的配置,把bean交给ApplicationContext 容器管理,通过其getBean方法获取指定bean对象。下面将在此基础上举例说明注解模式是怎么一回事。
一、配置spring.xml
说明:spring.xml的配置路径和springTest.xml一样,放在类路径下。
配置如下所示:(可以看出,在下面的配置中并没有配置任何bean实例,spring会在启动时扫描指定的包(com.chen指的是扫描所有以com.chen开头的包),
然后将相应bean注入到ApplicationContext容器中)
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 开启注解模式 --> <context:annotation-config/> <!-- 扫包(使用“注解模式”需要此配置)。服务器在启动时会扫描base-package所指定的包,并将相应的bean注入ApplicationContext容器。 --> <context:component-scan base-package="com.chen"></context:component-scan> </beans>
二、使用关键字“@Repository”将EmplDaoImpl 类的一个实例注入ApplicationContext容器中
这里使用了一个标识关键字“@Repository”,通过注解模式将模型层的实例注入ApplicationContext容器中需使用这个标识(那要是向ApplicationContext容器中注入控制层实例呢?参见“附:注入关键字说明”)。可以简单地理解,因为有了这个标识,spring在加载时扫到com.chen.dao包中的EmplDaoImpl 类时,自动地new了一个EmplDaoImpl 类的实例,并将这个实例注入到ApplicationContext容器中,这个实例名为“emplDaoImpl”。
@Repository("emplDaoImpl")//向ApplicationContext容器中注入EmplDaoImpl的一个实例 public class EmplDaoImpl extends BaseDaoImp<Empl>{ /** * 添加员工 * @param empl * @return */ public boolean addEmp(Empl empl){ String sql = "insert into t_empl values(SEQ_EMPL.nextval,?,?,?,to_date(?,'yyyy-mm-dd'),to_date(?,'yyyy-mm-dd'),?,?,?,?)"; return update(sql, empl.getEname(),empl.getPassword(),empl.getSex(), empl.getBirthday(),empl.getHiredate(),empl.getAdmin(), empl.getDeptno(),empl.getJob(),empl.getStatus()); } ... }
三、测试
新建一个测试类SpringTest2 。这个类中涉及到2个关键字:@Autowired、@Resource,它们都能将注入到ApplicationContext容器中的实例自动装载到当前类中--与第一个测试类SpringTest(手动装载)比较一下就会很容易发现它们的好处。
package com.chen.test; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.chen.dao.EmplDaoImpl; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring.xml") public class SpringTest2 { //自动装载1 //@Autowired //EmplDaoImpl emplDaoImpl; //自动装载2 @Resource EmplDaoImpl emplDaoImpl; @Test public void getEmplDaoImpl(){ System.out.println(emplDaoImpl); } }
打印信息:
com.chen.dao.EmplDaoImpl@13ff9d4
打印的hash码值说明该实例已获取到,我们可以调用emplDaoImpl的方法看下是否真的如此:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring.xml") public class SpringTest2 { //自动装载1 //@Autowired //EmplDaoImpl emplDaoImpl; //自动装载2 @Resource EmplDaoImpl emplDaoImpl; @Test public void getEmplDaoImpl(){ System.out.println(emplDaoImpl); } @Test public void getEmplById(){ System.out.println(emplDaoImpl.findEmplById(6)); } }
打印信息:
Empl [eid=6, ename=oo, password=123, sex=女, birthday=1999-01-01 00:00:00.0, hiredate=1999-01-01 00:00:00.0, admin=1, deptno=1, job=1, status=0, funs=null]
小结:通过以上两个实例可以大致了解到Spring的工作机制已经其核心特性--依赖注入,今后,我们便可以通过Spring配置来管理项目中的需要管理的bean对象了。
详情参见:
http://jinnianshilongnian.iteye.com/blog/1457223
http://jinnianshilongnian.iteye.com/blog/1457224
http://jinnianshilongnian.iteye.com/blog/1461055
附:注入关键字说明
@Repository、@Service、@Controller 和 @Component 将类标识为Bean
@Repository注解便属于最先引入的一批,它用于将数据访 问层 (DAO 层 ) 的类标识为 Spring Bean。具体只需将该注解标注在 DAO类上即可。同时,为了让 Spring 能够扫描类路径中的类并识别出 @Repository 注解,需要在 XML 配置文件中启用Bean 的自动扫描功能,这可以通过<context:component-scan/>实现。
为什么 @Repository 只能标注在 DAO 类上呢?这是因为该注解的作用不只是将类识别为Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。 Spring本身提供了一个丰富的并且是与具体的数据访问技术无关的数据访问异常结构,用于封装不同的持久层框架抛出的异常,使得异常独立于底层的框架。
Spring 2.5 在 @Repository的基础上增加了功能类似的额外三个注解:@Component、@Service、@Constroller,它们分别用于软件系统的不同层次:
- @Component 是一个泛化的概念,仅仅表示一个组件 (Bean) ,可以作用在任何层次。
- @Service 通常作用在业务层,但是目前该功能与 @Component 相同。
- @Constroller 通常作用在控制层,但是目前该功能与 @Component 相同。
详见:http://www.cnblogs.com/wql025/p/4806985.html