Spring Framework IoC以及DI的初步理解和实现

来源:互联网 发布:淘宝有没有隐形降权 编辑:程序博客网 时间:2024/05/16 02:00

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, stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%nlog4j.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容器图示:(官网上的.......)
由图看出,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" />

运行结果当然是这三个类的构造方法都被调用了…….

好了写到这里只写了一些很基础的东西。。。。
可能还会有错。。。。
不要骂我。。发现了请及时告诉我我好改。。。
蟹蟹。。。

原创粉丝点击