IOC有几种类型
两种,依赖注入和依赖查找
依赖注入分几种,是哪几种?
构造器constructor依赖注入和setter依赖注入
Spring的依赖注入的核心是Bean工厂. Bean工厂负责管理组件和它们之间的依赖关系.Spring中,这种bean用来查阅所有容器管理的组件.
你的应用程序需要通过BeanFactory接口来使用Spring的DI容器.也就是说,你的程序必须创建实现了BeanFactory接口的类来配置它的Bean和依赖关系的消息.
在Spring容器内拼凑Bean叫做装配。装配Bean的时候,你是在告诉容器需要哪些Bean以及容器如何使用依赖注入将它们 藕合在一起。
我们还是来用例子讲吧:
就以最常用的学生、课程、学藉、成绩来说:
业务层:
StudentService CourseService StudentServiceImpl CourseServiceImpl StudentDao CourseDao StudentDaoImpl CourseDaoImp
在业务层有两个业务组件:学生服务和课程服务。学生服务处理所有的和学生有关的事务,而课程服务负责和课程有关的功能。这些服务都通过接口来定义。
StudentService 接口如下:
public interface StudentService{ public Student getStuden(String id); public void createStudent(Student stu); public java.util.Set getCompletedCourse(Student stu); }CourseService接口如下: public interface CourseService{ public Student getCourse(String id); public void createCourse(Course course); public java.util.Set getAllCourse(); public void enrollStudentInCourse(Course course,Student stu) throws CourseException; } StudentServiceImpl是StudentService的实现: package com.springinaction.service.training; public class StudentServiceImpl implements StudentService{ private StudentDao stuDao; public StudentServiceImpl(StudentDao sDao){ stuDao=sDao; } public void setStudentDao(StudentDao sDao){ stuDao=sDao; } public Student getStudent(String id){ return stuDao.findById(id); } public void createStudent(Student stu){ stuDao.create(stu); } public java.util.Set getCompletedCourses(Student stu){ return stuDao.getCompletedCourses(stu); } }
StudentServiceImpl将很多职责委托给了StudentDao。StudentDao处理与数据库的交互来读写学生信息。StudentDao的实现类叫StudentDaoIpl.
在这里有两种方法将StudentDao引用赋给StudentServiceImpl:通过它的构造函数或通过setStudentDao()方法。
CoureseServiceImpl是CoureseService的实现:
package com.springinaction.service.training; import java.util.iterator; import java.util.Set; public class CourseServiceImpl implements CourseService{ private CourseDao courseDao; private StudentService studentService; private int maxStudents; public CourseServiceImpl(CourseDao courDao){ this.courseDao=courDao; } public void setStudentService(StudentService stuService){ this.studentService=stuService; } public void setMaxStudents(int maxStudents){ this.maxStudents=maxStudents; } public int getMaxStudents(){ return maxStudents; } public Course getCourse(String id){ return courseDao.findById(id); } public void createCourse(Course course){ courseDao.create(course); } public void enrollStudentInCourse(Course course,Student stu) throws CourseException{ if(course.getStudent().size()>=maxStudents){ throws new CourseException("Course is full"); } enforcePrerequisites(course,student); course.getStudent().add(student); courseDao.update(course); } private void enforcePrerequisites(Course course,Student student) throws CourseException{ Set completed= studentService.getCompletedCourse(student); Set prereqs=course.getPrerequisites(); for(Iternate iter=prereqs.iterator(); iter.hashNext();){ if(!completed.contains(iter.next())){ throws new CourseException("Prerequisites are not met.") } } } }
和StudentServiceImpl一样,CoureseServiceImpl是通过它的构造函数接受CourseDao参数。CourseDao的实现是CourseDaoImpl。
enrollStudentInCourse()方法在把学生添加到课程中之前先要调用enforcePrerequisites()方法。如果学生不能满足先决条件,enforcePrerequisites()方法抛出CourseException,enrollStudentInCourse将重新抛出这个异常。
注意enforcePrerequisites()方法使用了StudentService实现类来获得一个学生的所有已完成课程。这意味着除了CourseDao,CoureseServiceImpl还要与StudentService合作一满足先决条件这个业务需求。CoureseServiceImpl通过setStudentService()方法得到它的
StudentService,不象courseDao是通过构造函数得到。这样做的原因是因为courseDao在CoureseServiceImpl中经常被用到,所以不应该在创建CoureseServiceImpl的时候还没有设置CourseDao属性。
使用XML装配:
在Spring中,有几种容器都支持使用XML装配BEAN,包括:
XMLBeanFactory:一种简单的BeanFactory,它用java.io.InputStream载入上下文定义文件。
ClassPathXmlApplicationContext:一种应用上下文,它从类路径中载入上下文定义文件。
FileSystemXmlApplicationContext:一种应用上下文,它从文件系统中载入上下文定义文件。
XmlWebApplicationContext:一种基于Spring的Web应用系统上下文,它从Web应用系统上下文中载入上下文定义文件。
所有这些面向XML的容器都使用非常简单的XML文件来定义BEAN。上下文定义文件的根元素是.有多个子元素。每个元素定义了一个bean如何被装配到Spring容器中。
下面就是这个例子的XML配置
class="com.springinaction.Foo"/> class="com.sprionginaction.Bar"/>
这是个简单的BEAN装配XML文件在Spring配置了两个BEAN。
添加一个BEAN:
在Spring中对一个BEAN的最基本的配置包括Bean的ID和它的全称类名。
在上面的学生例子中,我们往文件中添加CourseDao和StudentDao的实现类的定义
原型与单实例:
默认情况下,Spring中的所有bean都是单例(singletons),这意味着Spring维护bean的唯一实例,所有的依赖对象引用同一实例。对
bean工厂的getBean()方法的每一次调用都返回同一个实例
在这里有个属性singletons,把它设为false就成了原型,如为TRUE,就是单例。
请大家注意每次用bean的名字调用getBean()方法都会获得一个这个BEAN的新实例,。如果BEAN使用的是有限资源,如数据库和网络连接的话这样使用就不好了。所有尽量不要把singletons设为false。除非确实需要。
通过Set方法注入依赖
public void setMaxStudents(int maxStudents){ this.maxStudents=maxStudents; } public int getMaxStudents(){ return maxStudents; }
Bean配置
class="com.springinactiong.Foo"> Foo MyFoo
假如为了限制每门课程的注册学生人数最多30人,
30
引用其他 bean 我们可以使用 元素来设置指向其他Bean的属性。
的子元素可以实现:
class="com.springinactiong.Foo"> class="com.springinactiong.Bar"/> class="com.springinaction.service.training.CourseDaoImpl"/> class="com.springinaction.service.training.studentService"/>
容器赋给courseService Bean 一个studentService实例,这样courseServiceImpl就不用自己寻找studentService了
内部 bean:
class="com.springinaction.service.training.CourseServiceImpl"/>
这种装配引用的方式的缺点是你无法在其他地方重用这个StudentServiceImpl实例,因为它是一个专门为courseService Bean建立的实例。
装配集合:
List bar1Set bar1 Map
Properties bar1 bar2
集合的装配就完了
下面就讲构造函数的注入
class="com.sprininaction.Foo"> 50
有两种方法来处理构造函数的不确定:
序号和类型
class="com.sprininaction.Foo"> ... ... class="com.sprininaction.Foo">Spring 30end