目录
传统方式建立一个对象:
1.最原始方法:
2..面向接口方法:
3.工厂模式
4.工厂+反射+配置文件 实现程序解耦
将实现类交给Spring管理
1.编写配置文件applicationContext.xml
2.编写测试类
SpringIOC与DI
1.springIOC与DI的关系
2.如何理解DI
3.如何使用DI
用户管理的DAO层接口:
package com.rosinante.spring.iocdemo; /* * 用户管理DAO接口 */ public interface UserDAO { public void save(); }以及他的实现类 :
package com.rosinante.spring.iocdemo; /* * DAO层实现类 */ public class UserDAOImpl implements UserDAO { public void save(){ System.out.println("UserDAO......"); } }写一个SpringIocDemo类来调用这个接口:
package com.rosinante.spring.iocdemo; import org.junit.Test; public class SpringIocDemo { @Test /* * 传统方式调用 */ public void demo(){ UserDAO userDAO = new UserDAOImpl(); userDAO.save(); } }面向接口的好处是实现了程序的多态,易拓展,但接口与实现类有耦合,例如将此例改为Hibernate实现,则需要创建一个Hibernate的实现类UserDAOHibernateImpl这意味着我们要切换底层实现类需要修改大量源代码。好的程序设计应满足OCP原则,在尽量不修改程序源码的基础上对程序进行拓展。
原先的接口方式接口与实现类直接产生关系,通过工厂避免直接产生关系。
例如创建一个BeanFactory的工厂类:
class BeanFactory{ public static UserDAO getUserDAO(){ return new UserDAOImpl(); } public static CustomerDAO getCustomerDAO(){ return new CustomerDAOImpl(); } ...... }把所有类的创建都交给工厂来实现,接口和实现类之间没有耦合,但是接口和工厂有耦合,要切换实现类的时候,还是要修改工厂类的源码,但好处是之前面向接口的方式需要修改很多类,工厂模式只需要修改工厂类。比如改为Hibernate方式实现时,只需要修改工厂类这一个类:
class BeanFactory{ public static UserDAO getUserDAO(){ return new UserDAOHibernateImpl(); } public static CustomerDAO getCustomerDAO(){ return new CustomerDAOImpl(); } ...... }例如有配置文件xml如下:
<bean id = "UserDAO" class = "xxx.UserDAOImpl"></bean>工厂类:
class BeanFactory{ public static Object getBean(String id){ //解析XML 找到对应的class //反射 Class class = Class.forName(); return class.newInstance(); } }实际上SpringIoc的底层实现就是通过这样的方式。
applicationContext是spring配置文件的默认名称,当然也可以使用其他的命名。
<?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"> <!-- spring入门配置 --> <bean id="userDAO" class="com.rosinante.spring.iocdemo.UserDAOImpl"></bean> </beans>如上我们将UserDAOImpl交给spring来管理。
之后如果需求改变,只需要将配置文件更改一下即可。
SpringIOC意为控制反转,即将对象的创建反转给了Spring,DI依赖注入是实现IOC的方式,DI依靠IOC容器。
面向对象中,对象之间有如下关系:
依赖 Class A{ ...... } Class B{ public void xxx(A a){ //xxx方法的参数需要类A的对象 类B对A产生了依赖 ...... } } 继承 Class A{ ...... } Class B extends A{ ...... } 聚合聚合是整体和个体之间的关系,例如球队和球员,英文字母和abc之间的关系
// 母亲 class Mother { // 母亲可以有自己孩子, 但是不确定什么时候生 private Children myChildren; } // 孩子 class Children { }DI就是将依赖的值设置进去,例如UserDAOImpl这个实现类中,添加一个属性name:
package com.rosinante.spring.iocdemo; /* * DAO层实现类 */ public class UserDAOImpl implements UserDAO { private String name; //增加的属性 public void setName(String name) { this.name = name; } public void save(){ System.out.println("UserDAO......"+name); } }那么我们在测试类中无法使用面向接口的方式赋值,必须通过创建一个实现类的对象来给name赋值:
public class SpringIocDemo { private Object bean; @Test /* * 传统方式调用 */ public void demo(){ //UserDAO userDAO = new UserDAOImpl(); //接口中没有set发法 只能使用实现类来创建对象 UserDAOImpl userDAO = new UserDAOImpl(); userDAO.setName("二狗"); userDAO.save(); } ...... }这样做的弊端有:
不能使用面向接口的方式编程必须手动设置属性值需要改变程序源代码在applicationContext.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"> <!-- spring入门配置 --> <bean id="userDAO" class="com.rosinante.spring.iocdemo.UserDAOImpl"> <!-- 属性注入 --> <property name="name" value="ergou"></property> </bean> </beans>运行测试类中的demo2方法,控制台成功打印。