写在前面的话
最近,给项目组成员培训了Spring 控制反转和依赖注入的原理,并自己做了个Lazy Coder版的Spring,现在给大家分享下,相互学习,有说得不对的欢迎指正。
由于代码较多,准备分成两篇博文来写,本文先介绍如何搭建spring开发环境,并讲解一些注意的知识点。
另:我们是使用xml配置来管理bean,并没有用到注释。
Spring基本配置
1. 准备一些业务类,我们准备一个BaseDao接口,就两个方法,add和update,它有两个实现类,分别为HibernateDaoImpl和JdbcDaoImpl,再准备一个BaseService接口,也有两个方法,add和update,它有一个实现类BaseServiceImpl,在BaseServiceImpl里,我们建立两个BaseDao接口,准备分别注入HibernateDaoImpl和JdbcDaoImpl,在BaseServiceImpl类里,add方法调用HibernateDaoImpl的add方法,update调用JdbcDaoImpl的update方法。
描述比较长,但应该很清晰,具体类代码如下:
package com.lazycoder.dao; public interface BaseDao { public void add(); public void update(); }
package com.lazycoder.dao.impl; import com.lazycoder.dao.BaseDao; public class HibernateDaoImpl implements BaseDao { @Override public void add() { System.out.println("HibernateDaoImpl add"); } @Override public void update() { System.out.println("HibernateDaoImpl update"); } }
package com.lazycoder.dao.impl; import com.lazycoder.dao.BaseDao; public class JdbcDaoImpl implements BaseDao { @Override public void add() { System.out.println("JdbcDaoImpl add"); } @Override public void update() { System.out.println("JdbcDaoImpl update"); } }
package com.lazycoder.service; public interface BaseService { public void add(); public void update(); }
package com.lazycoder.service.impl; import com.lazycoder.dao.BaseDao; import com.lazycoder.service.BaseService; public class BaseServiceImpl implements BaseService { public BaseDao hibernateDao; /** * 用于注入hibernateDaoImpl对象 * @param hibernateDao */ public void setHibernateDao(BaseDao hibernateDao) { this.hibernateDao = hibernateDao; } public BaseDao jdbcDao; /** * 用于注入jdbcDaoImpl对象 * @param jdbcDao */ public void setJdbcDao(BaseDao jdbcDao) { this.jdbcDao = jdbcDao; } public void add(){ System.out.println("BaseServiceImpl add"); hibernateDao.add(); } public void update(){ System.out.println("BaseServiceImpl update"); jdbcDao.update(); } }
2. 加入jar包,Spring依赖的基本包有下面两个:
dist/spring.jar
jakarta-commons/commons-logging.jar
2. 新建配置文件,在src目录下新建一个配置文件,名字任意,我们就叫spring.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-2.5.xsd"> <bean id="hibernateDao" class="com.lazycoder.dao.impl.HibernateDaoImpl"/> <bean id="jdbcDao" class="com.lazycoder.dao.impl.JdbcDaoImpl"/> <bean id="baseService" class="com.lazycoder.service.impl.BaseServiceImpl"> <!-- 通过name属性在baseServiceImpl里找到要注入的set方法,即 SetHibernateDao 通过ref属性在容器中找到对应id的实例化对像,即bean id="hibernateDao"... --> <property name="hibernateDao" ref="hibernateDao"/> <property name="jdbcDao" ref="jdbcDao"/> </bean> </beans>
3. 测试,新建一个Junit测试或者用main函数测试,我们使用Junit测试
package com.junit; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lazycoder.service.BaseService; public class JunitTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); BaseService baseService = (BaseService) context.getBean("baseService"); baseService.add(); baseService.update(); } }
输出:
BaseServiceImpl add
HibernateDaoImpl add
BaseServiceImpl update
JdbcDaoImpl update
知识点讲解
1. 在项目中所有的bean,需要交给spring管理的,都需要在配置文件里,添加一个bean节点,id理论上任意,但应该规范,一般为类的接口首字母大写。class为类所在的全路径
2. service要调用dao层代码,在service中定义dao接口成员,而不是具体的dao类,我们要面向接口编程,这样我们可以通过配置来切换dao接口真正的实现类,而不需要改java代码。
3. property节点里的ref属性值,必须是在bean节点中定义过的id,这样才可以找到要注入的dao类。
4. property节点里的name属性值,spring会将它格式化成"set+首字母大写",如hibernateDao,格式化后即setHibernateDao,再到父节点bean里对应的类里BaseServiceImpl查找set方法,并注入。
5. 注入的时候是根据set方法来注入的,不是根据成员变量,也就是说我们把 public BaseDao hibernateDao;改成public BaseDao abcDao;程序依然可以运行,但是如果把public void setHibernateDao(BaseDao hibernateDao)改成public void setAbcDao(BaseDao hibernateDao),运行就会报错了