天天看点

Spring学习笔记---IOC与DI传统方式建立一个对象:将实现类交给Spring管理SpringIOC与DI

目录

传统方式建立一个对象:

1.最原始方法:

 2..面向接口方法:

3.工厂模式

 4.工厂+反射+配置文件 实现程序解耦

将实现类交给Spring管理

1.编写配置文件applicationContext.xml

2.编写测试类

SpringIOC与DI

1.springIOC与DI的关系

2.如何理解DI

3.如何使用DI

传统方式建立一个对象:

1.最原始方法:

UserDAO userDao = new UserDAO();
           

 2..面向接口方法:

用户管理的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原则,在尽量不修改程序源码的基础上对程序进行拓展。

3.工厂模式

原先的接口方式接口与实现类直接产生关系,通过工厂避免直接产生关系。

例如创建一个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();
    }
    ......
}
           

 4.工厂+反射+配置文件 实现程序解耦

例如有配置文件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的底层实现就是通过这样的方式。

将实现类交给Spring管理

1.编写配置文件applicationContext.xml

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来管理。

2.编写测试类

package com.rosinante.spring.iocdemo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringIocDemo {
	private Object bean;
	@Test
	/*
	 * 传统方式调用
	 */
	public void demo(){
		UserDAO userDAO = new UserDAOImpl();
		userDAO.save();
	}
	@Test
	/**
	 * Spring方式的调用
	 */
	public void demo2(){
		//创建Spring的工厂
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		//传入id:UserDAO 返回UserDAO的实例
		UserDAO userDAO = (UserDAO)applicationContext.getBean("userDAO");
		userDAO.save();
	}
}
           

之后如果需求改变,只需要将配置文件更改一下即可。

SpringIOC与DI

1.springIOC与DI的关系

SpringIOC意为控制反转,即将对象的创建反转给了Spring,DI依赖注入是实现IOC的方式,DI依靠IOC容器。

2.如何理解DI

面向对象中,对象之间有如下关系:

  • 依赖
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();
	}

	......

}
           

这样做的弊端有:

  1. 不能使用面向接口的方式编程
  2. 必须手动设置属性值
  3. 需要改变程序源代码

3.如何使用DI

在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方法,控制台成功打印。

Spring学习笔记---IOC与DI传统方式建立一个对象:将实现类交给Spring管理SpringIOC与DI