Spring IOC 学习笔记

注:该篇文章会与我的个人博客同步更新。欢迎移步https://cqh-i.github.io/体验更好的阅读效果。

什么是 IOC

全称 Inversion of Control(控制反转)。将对象的创建权反转给了Spring。

与传统方式对比

  传统方式的调用中,接口和实现类之间的耦合度太高,不满足OCP原则(对修改关闭,对扩展开放)。如有一个接口和它的两个实现类:

/*
* 某功能接口
*/
public interface UserDao{
	public void save();
}

/**   
 * 该功能接口的实现类一
 */  
public class UserDaoImpl1 implements UserDao{
	@Override
	public void save() {
		System.out.println("UserDaoImpl1执行了。。。");
	}
}

/**   
 *该功能接口的实现类二
 */  
public class UserDaoImpl2 implements UserDao{
	@Override
	public void save() {
		System.out.println("UserDaoImpl2执行了。。。");
	}
}

  当我们需要切换接口的实现类时,传统方式弊端就出来了,UserService userService = new UserDaoImpl1();改为UserService userService = new UserDaoImpl2();一个好的程序设计应尽量满足OCP原则,在尽量不修改程序源码的基础上对程序进行扩展。
  上述接口和实现类之间的耦合可以通过工厂模式来解决。

public class BeanFactory {
	public static UserDao getUserDao() {
		return new UserDaoImpl1();
	}
}

  现在接口和实现类之间没有耦合,但是工厂和接口之间有耦合。如我们要切换接口实现类还要要去修改工厂类里面的方法,如改为return new UserDaoImpl2();
  要解决上述问题,需要通过工厂模式+反射+配置文件来实现程序解耦合。

<bean id="userDao" class="xxx.UserDaoImpl1"></bean>
class BeanFactory {
    public static Object getBean(String id){
        //解析XML
        //反射
        Class clazz = Class.forName("xxxImpl");
        return clazz.newInstance();
    }
}

IOC的底层实现原理

  上述的工厂模式+反射+配置文件方式就是IOC的底层实现原理。

 将实现类交给Spring管理

  1. 创建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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	<bean id="UserDao" class="com.itheima.spring.demo1.UserDaoImpl1"></bean>
</beans>
  1. 编写测试类
	@Test
	public void test() {
		// 创建Spring的工厂
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao userDao = (UserDao) applicationContext.getBean("UserDao");
		userDao.save();
	}

  运行结果:UserDaoImpl1执行了。。。
  通过这种方式,当我们需要切换底层实现类时,只需要修改配置文件,而不用去修改源代码。

IOC 和 DI

DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。

  假如UserDaoImpl1中有一个属性name(String),

public class UserDaoImpl1 implements UserDao{
	private String name;
	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public void save() {
		System.out.println("UserDaoImpl1执行了。。。"+name);
	}
}

  那么可以在配置文件中,注入属性的值

<bean id="UserDao" class="com.itheima.spring.demo1.UserDaoImpl1">
	<property name="name" value="WS"/>
</bean>

  执行测试方法

@Test
public void test() {
	// 创建Spring的工厂
	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	UserDao userDao = (UserDao) applicationContext.getBean("UserDao");
	userDao.save();
}

  运行结果:UserDaoImpl1执行了。。。WS

Spring IOC 注解开发方式

  1. 引入约束:引入context约束。
  2. 开启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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- 使用IOC的注解开发,第一步需要配置扫描,哪些包下的类使用IOC的注解 -->
	<context:component-scan base-package="com.itheima.spring.demo1"></context:component-scan>
</beans>
  1. 在类上添加注解
@Component("UserDao")//相当于在xml里配置<bean id="userDao" class="com.lee.spring.demo1.UserDaoImpl"/>
public class UserDaoImpl1 implements UserDao{
	@Override
	public void save() {
		System.out.println("UserDaoImpl1执行了。。。");
	}
}

4.编写测试类

	@Test
	public void test() {
		// 创建Spring的工厂
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao userDao = (UserDao) applicationContext.getBean("UserDao");
		userDao.save();
	}

运行结果:UserDaoImpl1执行了。。。

注解方式设置属性的值

注解方式设置属性的值,可以没有set方法的。

  • 属性如果有set方法,需要将属性注入的注解添加到set方法上
  • 属性如果没有set方法,需要将属性注入的注解添加到属性上
@Component("UserDao") // 相当于在xml里配置<bean id="userDao" class="com.lee.spring.demo1.UserDaoImpl"/>
public class UserDaoImpl1 implements UserDao {
   @Value("李四")
   private String name;
   /*	@Value("李四")
   	public void setName(String name) {
   		this.name = name;
   	}*/
   @Override
   public void save() {
   	System.out.println("UserDaoImpl1执行了。。。"+name);
   }
}

运行结果:UserDaoImpl1执行了。。。李四

Sping的IOC的注解详解

  • @Component:组件 修饰一个类,将这个类交给Spring管理。

(这个组件可以修饰任何一层的类,包括Dao,Service,web层。因为分层结构不明显,后来提供了三个衍生类,但目前来讲三个注解和Component功能一样,只是建议使用三个衍生注解,后面的版本可能会进行扩展)
三个衍生注解(功能类似)
@Controller:web层
@Service:service层
@Repository:dao层

属性注入的注解
  • 普通属性:
      @Value:设置普通属性的值
  • 对象类型属性:
      @Autowired:设置对象属性的值,但是按照类型完成属性注入
      替代注解@Resurce:设置对象属性的值,按照名字完成注入
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值