【Spring】 1. IOC

文章目录

    • 【Spring】 1. IOC
      • 学习框架前的引言
      • 1. Spring 简介
          • 1.1 Spring 概述
          • 1.2 Spring 核心
          • 1.3 Spring 下载
          • 1.4 sts
      • 2. IOC
          • 2.1 原始方式
          • 2.2 IOC 底层原理
          • 2.3 BeanFactory 工厂类
          • 2.4 入门程序
          • 2.5 bean 的常用属性
      • 3. DI
          • 3.1 注入方式
          • 3.2 注入复杂属性
          • 3.3 命名空间注入
          • 3.4 SpEL 注入
      • 4. 基于注解的Bean管理
          • 4.1 配置文件
          • 4.2 组件注解
          • 4.3 作用域注解
          • 4.4 属性注解
          • 4.5 基于xml和注解管理Bean的区别

【Spring】 1. IOC

学习框架前的引言

框架要学什么?

  • 框架的使用
  • 框架的底层原理

框架和类库的区别

  • 类库:就对某个功能的实现,基本上都是一些功能开发的工具。类库相当于挖掘机、推土机、扳手
  • 框架:是对项目整体的架构和设计。框架就相当于建筑物的结构,比如电梯井预留好,只好放入电梯就可以工作了。

框架的难度

  • 完成项目,必须依照框架定义好的规范。如果不符合规范,出现错误很难调试和定位。
  • 新增术语

框架的实现方式

  • 基于xml配置文件的
  • 基于注解的



1. Spring 简介

1.1 Spring 概述

​ Spring是一个开源的设计层面框架,于2003 年兴起的由Rod Johnson创建。Spring是一个分层的JavaSE/EE的一站式、轻量级、开源框架。

  • 一站式:在JavaEE的三层结构中,每一层都提供了不同的解决方案。
  • 轻量级:Spring 是非侵入性的 ,在 IOC 和 AOP 的基础上可以整合各种企业应用的的第三方类库。

1.2 Spring 核心
  • IOC(Inversion of Control):控制反转。降低了业务对象替换的复杂性,提高了组件之间的解耦。

  • AOP(Aspect Oriented Programming):面向切面编程。允许将一些通用任务(如安全、事务、日志等)进行集中式管理,从而实现更好的复用。


1.3 Spring 下载

​ 官网地址:https://spring.io/
​ 类库下载:http://repo.spring.io/release/org/springframework/spring/

1.4 sts

​ sts(spring tool suite):Spring 工具套件。它是一个基于Eclipse的开发环境, 用于开发Spring应用程序。它提供了一个现成的使用环境来实现调试、运行和部署你的Spring应用程序。包括为关键的的服务器和云计算,Git, Maven, AspectJ和最新的Eclipse版本提供整合支持。

​ 各Eclipse版本的sts下载地址 : https://spring.io/tools/sts/legacy。

​ sts 在线安装:使用Eclipse Marketplace ,可直接搜索 sts 安装。



2. IOC

​ IOC(Inversion of Control)中文含义是控制反转。

​ 当需要某个对象实例时,在传统的程序设计过程中,通常由调用者来创建该实例。但在Spring里,创建对象的工作由Spring来完成,因此称为控制反转。IOC 降低了业务对象替换的复杂性,提高了组件之间的解耦。


2.1 原始方式
// Dao层接口
public interface UserDao {	
	void insert();
}
// Dao层实现类
public class UserDaoImpl implements UserDao{
	@Override
	public void insert() {
		System.out.println("插入一条数据...");
	}
}
//原始的方式
UserDao userDao = new UserDaoImpl();
userDao.insert();

​ 原始方式就是手动实例化对象。如果项目中有10处使用 UserDao实例,则需要实例化10次对象。问题在于,当 UserDao的实现方式发生变化时(比如实现类是UserDaoImpl2),这10处位置都需要修改。

​ 换句话说,组件之间的耦合性较高,业务对象替换的比较复杂。


2.2 IOC 底层原理
  • Bean工厂

​ 把组件实例化过程交给工厂,需要实例化对象的时候,调用工厂类的方法统一处理。

public interface BeanFactory {
	//根据id获得bean实例
	Object getBean(String id);	
}
  • 根据全路径类名获得类的实例

    通过反射机制,根据全路径类名,获得类的实例

/**
 * 根据全路径类名获得类的实例
 * 		技术点:反射
 * @param className 全路径类名
 * @return 类的实例
 * @throws Exception
 */
private Object getInstanceByClassName(String className) throws Exception{
	//获得类的加载器
	ClassLoader classLoader = getClass().getClassLoader();
	//加载类
	Class<?> cls = classLoader.loadClass(className);
	//创建实例
	Object obj = cls.newInstance();		
	return obj;
};
  • 配置文件

    在class 类路径下新建配置文件“application-config.xml”,统一对需要实例化的对象进行配置。



<beans>
	
	<bean id="UserDao" class="com.bodhixu.ssm.UserDaoImpl"/>
beans>
  • 读取并解析配置文件

    读取配置文件,并通过dom4j进行解析。并通过反射生成实例,放入map集合

/**
 * 读取配置文件,获得bean实例
 * 		技术点:dom4j
 * @param xmlPath 配置文件路径
 * @return bean的map集合
 * @throws DocumentException 
 */
private Map<String, Object> initConfig(String xmlPath) throws Exception {		
	Map<String, Object> beanMap = new HashMap<>();		
	//读取配置文件,获得输入流
	InputStream is = getClass().getResourceAsStream(xmlPath);
	//创建解析器
	SAXReader reader = new SAXReader();
	//加载数据,获得文档模型
	Document doc = reader.read(is);
	//获得文档根节点
	Element rootElement = doc.getRootElement();
	//获得所有bean的子节点
	List<Element> beanElements = rootElement.elements("bean");
	//遍历bean子节点
	for (Element element : beanElements) {
		//获得id属性
		String id = element.attributeValue("id");
		//获得class属性
		String cls = element.attributeValue("class");
		//根据类名获得类的实例
		Object obj = getInstanceByClassName(cls);
		//放入map集合
		beanMap.put(id, obj);
	}		
	return beanMap;
}
  • 根据id获得bean实例

    提供 get 方法,根据 id 返回 bean 对象

public Object getBean(String id) {
  return beanMap.get(id);
}

2.3 BeanFactory 工厂类

【Spring】 1. IOC_第1张图片

  • BeanFactory:接口

  • ApplicationContext:接口

  • ClassPathXmlApplicationContext:实现类,加载类路径下的配置文件

  • FileSystemXmlApplicationContext:实现类,加载文件系统下的配置文件


2.4 入门程序
  • 导入Spring IOC 所依赖的 jar 包

【Spring】 1. IOC_第2张图片

  • 在类路径下,创建配置文件“application-config.xml”,并配置
    【Spring】 1. IOC_第3张图片

<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="userDao" class="com.bodhixu.ssm.UserDaoImpl"/>

beans>
  • 创建 ApplicationContext 对象,通过其获得bean实例。
ApplicationContext context = 
    	new ClassPathXmlApplicationContext("/application-config.xml");
UserDao userDao = (UserDao) context.getBean("UserDao");

2.5 bean 的常用属性
  • id:bean对象的名字,不能包含特殊字符
  • name:和id功能一致,可以包含特殊字符
  • class:bean对象对应类的全路径
  • scope:设置bean的作用域
    • singleton:单例模式,默认的
    • prototype:多例模式
    • request:将实例存入到request域中
    • session:将实例存入到session域中



3. DI

​ DI(Dependency Injection)依赖注入,用来实现对bean对象属性赋值。


3.1 注入方式

​ DI 的实现方式主要有构造器注入和 setter注入,另外其他一些方式如工厂方法注入(很少使用,不推荐)。

  • 构造器注入

必须提供有参构造方法

<bean id="Book" class="com.bodhixu.ssm.demo01.Book">
	<constructor-arg name="name" value="Java"/>
	<constructor-arg name="price" value="200"/>
bean>
  • setter 注入

    必须提供 setter 方法

<bean id="Book" class="com.bodhixu.ssm.demo02.Book">
	<property name="name" value="Oracle"/>	
	<property name="price" value="200"/>
bean>

3.2 注入复杂属性
  • 注入 bean 对象
<bean id="book" class="com.bodhixu.ssm.demo03.Book">
	<property name="name" value="Oracle"/>	
	<property name="price" value="200"/>
bean>


<bean id="student" class="com.bodhixu.ssm.demo03.Student">
	<property name="name" value="小张"/>
	<property name="book" ref="book" />
bean>
  • 注入数组、集合

<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="book1" class="com.bodhixu.ssm.demo04.Book">
		<property name="name" value="java"/>
		<property name="price" value="100"/>
	bean>
	
	<bean id="book2" class="com.bodhixu.ssm.demo04.Book">
		<property name="name" value="orcle"/>
		<property name="price" value="200"/>
	bean>
	
	
	<bean id="Student" class="com.bodhixu.ssm.demo04.Student">
	
		
		<property name="arr">
			<array>
				<value>arrItem1value>
				<value>arrItem2value>
			array>
		property>		
		
		
		<property name="list">
			<list>
				<value>listItem1value>
				<value>listItem2value>
			list>
		property>
		
		
		<property name="set">
			<set>
				<value>listItem1value>
				<value>listItem2value>
			set>
		property>
		
		
		<property name="map">
			<map>
				<entry key="mapkey1" value="mapValue1" />
				<entry key="mapkey2" value="mapValue2" />
			map>
		property>
	
				
		
		<property name="books">
			<list>
				<ref bean="book1"/>
				<ref bean="book2"/>
			list>
		property>
	bean>
	
beans>

3.3 命名空间注入

​ 为了简化XML文件的属性配置,Spring从2.5后,引入了新的p命 名空间。

  • 声明p命名空间,可以通过 sts 实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0AmksVvj-1587633631341)(img/img7.png)]

xmlns:p="http://www.springframework.org/schema/p"
  • 采用 p 命名空间注入属性值
<bean id="Book" class="com.bodhixu.ssm.demo05.Book"
		p:name="HTML" p:price="60"/>
  • Spring从3.0后,引入了新的c命 名空间。

3.4 SpEL 注入

​ SpEL(Spring Expression Language)Spring的表达式语言。
​ 语法:#{SpEL}

<bean id="book1" class="com.bodhixu.ssm.demo06.Book">
	<property name="name" value="Oracle"/>	
	<property name="price" value="200"/>
bean>


<bean id="book2" class="com.bodhixu.ssm.demo06.Book">
	<property name="name" value="#{'new' + book1.getName()}"/>	
	<property name="price" value="#{200+20}"/>
bean>



4. 基于注解的Bean管理

​ Spring 中对 Bean 的管理有两种方式,一种是通过 xml 配置来管理,一种是通过注解来管理。

4.1 配置文件
  • 新建配置并引入context约束,可以通过 sts 实现·
<context:component-scan base-package="com.bodhixu.ssm" />
  • 开启注解扫描

<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-4.3.xsd">
  
	
	<context:component-scan base-package="com.bodhixu.web.bean"/>
	
	
	
 	
 	
 	 
 	 
beans>

4.2 组件注解

组件注解的类型

​ 组件注解注释在类上,共有4个,他们作用一样,只是语义化了。暂时我们使用 @Component 注解,在后面的SrpingMVC 中会使用其他注解。

  • @Component: 组件
  • @Controller : 控制组件(WEB层)
  • @Service :业务组件(业务层)
  • @Repository:仓库组件(持久层)

组件名称的设置

​ 给组件注入名称相当于 xml 配置中的 id 属性,设置名称有3种方式。

  • 通过value属性指定组件名称
@Component(value="book")
public class Book {}
  • 只有一个属性,可以省略value
@Component("book")
public class Book {}
  • 未指定属性名称,默认使用类名小写作为组件名
@Component //名称默认是book
public class Book {}

4.3 作用域注解

​ 使用 @Scope 可以设置Bean的作用域,作用同 xml 中配置 bean 的作用域一样。常用的有 singleton 单例模式和 prototype 多例模式。默认是单例的。

@Scope(value="prototype") //单一属性可以省略value=

4.4 属性注解

​ 使用注解注入属性,对象不需要setter方法。如果有setter方法,注解需要写在setter方法上。

  • @Value:普通属性注入
@Component("book3")
public class Book {
    
	@Value(value="java编程") //单一属性可以省略value=
	private String name;
	@Value("100")
	private int price;
    
}
  • @Resource:使用bean的名字注入
@Component("book4")
public class Book {}

@Component("stu1")
public class Student {
	
	@Resource(name="book4")
	private Book book;

}
  • @Autowired:自动注入bean
@Repository
public class UserDao {
	public void insert() {
		System.out.println("UserDao insert...");
	}	
}

@Service
public class UserService {
	@Autowired
	private UserDao userDao;	
	public void regist() {
		userDao.insert();
	}	
}

class Test {
	@org.junit.jupiter.api.Test
	void test() {
		ApplicationContext context = new ClassPathXmlApplicationContext("/application-config.xml");
		UserService service = (UserService) context.getBean("userService");
		service.regist();		
	}
}


4.5 基于xml和注解管理Bean的区别
  • 注解方式管理,简单快捷,对于自己实现的类,建议使用
  • xml方式管理,相对较繁琐,但对于第三方的类,比如jar包引入的类,需要使用xml方式配置

【Spring】 1. IOC_第4张图片

你可能感兴趣的:(主流框架,spring,ioc,java)