Spring Framework IoC以及DI的理解和实现(一)—–> 通过配置xml
咳咳,最近一周接触到了Spring。觉得记下来很快就会忘记,于是乎加上从网上查到的一些资料……废话就不说了
首先需要了解一下什么是IoC和DI还有bean
IoC(Inversion of Control):控制反转,就是通过容器来创建对象,对象的创建由程序自己控制,而不是以以往硬编码的方式来创建依赖关系。
DI:依赖注入,都说是IOC的一种实现方式,是实现IoC的一个过程。就是将依赖对象的创建和绑定转移到被依赖对象类的外部来实现(这句话抄来的)。
bean:在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是由Spring IoC容器实例化,组装和以其他方式管理的对象。否则,bean只是应用程序中的许多对象之一。Bean和它们之间的依赖关系反映在容器使用的配置元数据中。
First
首先要把Spring套用到项目中,在你的项目里要加入两个配置文件。我使用了maven,于是乎就把这两个配置文件放在一个新建的Source Folder下面了。
1.名为log4j.properties的日志文件配置,如果你已经有这个文件的话就把以下配置加进去,没有的话就新建一个。导包什么的就不再说了。
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
log4j.category.org.springframework.beans.factory=INFO
2.然后需要建立一个beans.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.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
</beans>
The bean definition(bean的定义)
Property | Explained in… |
---|---|
class | 要指定一个实际类 |
id/name | 唯一且遵守bean命名约定 |
scope | 不设定则默认为singleton,单例 |
constructor arguments | 体现继承关系,如果没有就不用 |
properties | “Dependency Injection” |
autowiring mode | “Autowiring collaborators” |
lazy-initialization mode | “Lazy-initialized beans” |
initialization method | “Initialization callbacks” |
destruction method | “Initialization callbacks” |
通过配置xml方式实现IoC和DI
由图看出,IoC需要读取“元数据”,这里xml配置就相当于“元数据”。
First
假设我们要处理学生信息的管理,首先我们先写好Student类,和StudentDao实现层接口和StudentDaoImpl实现类,以及StudentBiz业务层接口和StudentBizImpl业务层实现类。
1.Student类我就不详细写了……(包含了Student 的id,sname 以及get,set方法和有参、无参的构造方法…..)
2.StudentDao接口如下:
import com.yc.bean.Student;
public interface StudentDao {
public void addStudent(Student student); //添加学生信息
public boolean isStudentExist(Student student); //查看此学生信息是否已经存在
}
3.StudentDaoImpl实现类如下:
import java.util.Random;
import com.yc.bean.Student;
import com.yc.dao.StudentDao;
public class StudentDaoImpl implements StudentDao {
public StudentDaoImpl() {
System.out.println("StudentDaoImpl构造方法...");
}
@Override
public void addStudent(Student student) {
System.out.println("在StudentDaoImpl添加"+student+"...");
}
@Override
public boolean isStudentExist(Student student) {
Random r = new Random();
return r.nextBoolean();
}
}
4.StudentBiz业务层接口如下:
import com.yc.bean.Student;
public interface StudentBiz {
public void addStudent(Student student);
}
5.StudentBizImpl业务层实现如下:
import com.yc.bean.Student;
import com.yc.biz.StudentBiz;
import com.yc.dao.StudentDao;
public class StudentBizImpl implements StudentBiz {
private StudentDao studentDao;
public StudentBizImpl() {
System.out.println("StudentBizImpl构造方法...");
}
@Override
public void addStudent(Student student) {
if(studentDao.isStudentExist(student)){
throw new RuntimeException("学生已经存在不能再添加");
}
studentDao.addStudent(student);
}
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
System.out.println("spring还偷偷的将studentDao对象注入到StudentBizImpl中...");
}
}
Second
然后在beans.xml里就可以写入
<bean id="student" class="所在包名.Student"></bean>
//配置Bean,spring容器就可以创建对象
然后再跑到测试类里测试一下:
public class AppTest extends TestCase{
public AppTest( String testName ){
super( testName );
}
public static Test suite(){
return new TestSuite( AppTest.class );
}
public void testApp(){
//实例化容器,spring要在自己创建的时候,就读取beans.xml并通过反射机制创建对象,这里可以添加多个配置文 件"beans.xml","XXX.xml"逗号隔开。
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
//ApplicationContext是BeanFactory的子接口,代表Spring IoC容器,并负责实例化,配置和组装上述bean。
//而BeanFactory是一个非常强大的接口,提供了能够管理任何类型的对象的高级配置机制。
//再从容器中取出bean
Student student = (Student)context.getBean("student"); //这里的student,就是beans.xml里的id
student.setId(1);
student.setSname("张三");
System.out.println(student);
Student s2 = (Student)context.getBean("student"); //再创建一个学生对象
System.out.println(student.hashCode()+"\t"+s2.hashCode());//通过比较结果判断是单例还是多例
}
运行结果:
Student构造方法...
Student [id=1, sname=章㤾]
5892322 5892322
然后我们可以得出一个结论,spring创建的是单例
Third
然后我们对beans.xml继续写,实现DI
<!--通过spring IOC创建 dao-->
<bean id="studentDao" class="所在包.StudentDaoImpl"></bean>
<!--通过spring IOC创建 biz-->
<bean id="studentBiz" class="所在包.StudentBizImpl">
<property name="studentDao" ref="studentDao"></property>
//关于这里的配置我是这样理解的:业务层依赖于实现层,通过调用业务层就可以实现调用实层的方法,id和ref体现了依赖关系
</bean>
然后跑到测试类测试一下:
public void testApp2(){
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
Student student = (Student)context.getBean("student");
student.setId(1);
student.setSname("张三");
StudentBiz sb = (StudentBiz)context.getBean("studentBiz");
sb.addStudent(student);
}
运行结果:
Student构造方法...
StudentDaoImpl构造方法...
StudentBizImpl构造方法...
spring还偷偷的将studentDao对象注入到StudentBizImpl中...
在StudentDaoImpl添加Student [id=1, sname=张三]...
关于构造方法DI的栗子
public class ConstructorDi {
private Integer x; //苹果的编号
private String y; //苹果的说明
private Apple apple; //苹果他自己
public ConstructorDi(Integer x, String y, Apple apple) {
super();
this.x = x;
this.y = y;
this.apple = apple;
}
public ConstructorDi() {
}
@Override
public String toString() {
return "ConstructorDi [x=" + x + ", y=" + y + ", apple=" + apple + "]";
}
}
接着beans.xml:
<!-- 构造方法di -->
<bean id="cd" class="所在包名.ConstructorDi">
<!-- 这是第一种写法
<constructor-arg value="77"/>
<constructor-arg value="appleSister"/>
<constructor-arg ref="apple"/>
-->
<!--这是第二种写法
<constructor-arg name="x" value="77"/>
<constructor-arg name="y" value="appleSister"/>
<constructor-arg name="apple" ref="apple"/>
-->
<!--第三种写法 -->
<constructor-arg index="0" value="77"/>
<constructor-arg index="1" value="appleSister"/>
<constructor-arg index="2" ref="apple"/>
</bean>
去测试类瞧瞧:
public void testApp(){
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
ConstructorDi cd = (ConstructorDi) context.getBean("cd");
System.out.println(cd);
}
运行结果:
ConstructorDi [x=77, y=appleSisiter, apple=Apple [aid=null]]
基于SetterDI的栗子
public class FavoriteBiz {
private TagDao tagDao;
private FavoriteDao favoriteDao;
public TagDao getTagDao() {
return tagDao;
}
public void setTagDao(TagDao tagDao) {
this.tagDao = tagDao;
}
public FavoriteDao getFavoriteDao() {
return favoriteDao;
}
public void setFavoriteDao(FavoriteDao favoriteDao) {
this.favoriteDao = favoriteDao;
}
public FavoriteBiz() {
super();
System.out.println("FavoriteBiz的构造方法");
}
}
beans.xml是这样的:
<bean id="favoriteBiz" class="com.yc.bean.FavoriteBiz" depends-on="favoriteDao,tagDao">
<property name="favoriteDao" ref="favoriteDao" />
<property name="tagDao" ref="tagDao" />
</bean>
<bean id="tagDao" class="com.yc.bean.TagDao" />
<bean id="favoriteDao" class="com.yc.bean.FavoriteDao" />
运行结果当然是这三个类的构造方法都被调用了…….
好了写到这里只写了一些很基础的东西。。。。
可能还会有错。。。。
不要骂我。。发现了请及时告诉我我好改。。。
蟹蟹。。。