Spring入门
Spring简介
-
传统javaWeb开发的缺点:
- 开发流程繁琐,各个类之间耦合度较高,各个类的创建时机是在用户连接服务器的时候,需要使用到相关的资源的时候才会创建对象,耗时较长内存占用较高
-
Spring框架的优点
- 方便解耦,简化开发:解决企业级应用开发的业务逻辑层和其他各层的耦合问题。
- AOP编程支持:Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
- 声明式事务的支持:只需要通过配置就可以完成对事务的管理,而无需手动编程
- 方便程序的测试:Spring对Junit4支持,可以通过注解方便的测试Spring程序
- 方便集成各种优秀框架:可以使用spring集成其他的框架比如mybatis,hibernate,struts等
- 降低JavaEE API的使用难度:Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
-
spring概述
- 官网地址
- https://spring.io/
- 简介:
- Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IOC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 SpringMVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架 .
- 分层:spring是由底层核心容器(IOC),中间层组件AOP 等,上层的MVC等组件构成,但是每个组件都可以单独使用。
- JavaSE/EE:支持javaSE与javaEE的解决方案
- full-stack:丰富的组件,有从dao层到service层到web层的解决方案
- 轻量级:轻量级,对于内存占用小,代码入侵程度低
- Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IOC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 SpringMVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架 .
- 官网地址
-
Spring体系结构
-
底层是核心容器
- Beans:与core组合
- Core:主要实现了IOC与DI
- Context:基于前两个模块,但是增加了支持JavaEE特性,提供将第三方库集成到Spring的功能,如缓存(EhCache,JCache)和任务调度(CommonJ,Quartz)等。
- SpringEL表达式:模块提供强有力的在运行时查询和操作对象的语言。这种语言支持获取和设置属性、方法执行、获取数组或集合中的对象、逻辑计算、命名变量,在Spring的IoC容器中获得对象
-
中间层技术
- AOP:模块提供切面编程的实现。可以自定义方法拦截和切入点
- Aspects:模块提供与AspectJ的集成
- instrument:模块为特定的服务器提供类加载服务,
spring-instrument
模块是集成了Tomcat。
-
应用层技术
- 数据访问与数据集成
- Web集成
- Web实现
-
基于Test测试
-
IOC
-
IOC inversion of control 控制反转
- 在传统的web开发过程中各个类之间的耦合度较高,在使用不同的类的时候是依赖new或者静态等方式去创建一个对象,不同的类之间耦合度较高。
- 解决方案:通过配置文件的方式实现创建实体类与创建时机的解耦,ioc是一种解决方案,程序把实体类的创建权移交出去,把对与实体类的创建权力移交给容器管理,运用控制反转实现了解耦
-
解耦思路分析
- 在使用jdbc注册驱动的时候存在两种方式,一种是通过DriverManager.reisterDriver()来加载相关类到内存中实现注册驱动,还有一种方式是使用Class.forName()方式。第一种方式只是是使用new的方式在内存中创建实体类,第二种方式是通过传递类的全限定类名然后通过反射的方式创建对象,如果驱动文件发生了变化,第一种方式需要去修改java代码,但是第二种方式只是需要修改配置文件就可以,这样就实现了注册驱动与java代码的解耦,那么通过这中方式可以使得创建一个具体实现类与java代码的解耦,在开发过程中需要使用到大量的new的方式去创建对象,那么可以通过一种方式对一个项目中所有的new一个实体类的这种创建方式进行统一的管理,并且可以实现解耦,这就是IOC的基础实现思路
- 实现思路:
- 管理所有实体类的创建方式的解决方案:工厂设计模式
- 实现创建实体类与java代码的解耦解决方案:配置文件与反射创建实体类
-
控制反转的实现
-
数据准备
-
实体类与接口
//实现类 package com.wx.services.imp; import com.wx.services.UserService; public class UserServiceImp implements UserService { @Override public void save() { System.out.println("spring的你好世界"); } } //接口 package com.wx.services; /** * user类的接口 */ public interface UserService { /** * 业务层的保存方法 */ void save(); }
-
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="test" class="com.wx.services.imp.UserServiceImp"> </bean> </beans>
-
实现一个简单的IOC
import com.wx.services.UserService; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.junit.Test; import java.io.InputStream; import java.util.HashMap; import java.util.List; /** * 使用dom4j对xml进行解析 * 实现IOC */ public class IOCTest { @Test public void test() throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException { HashMap<String, Object> IOCContainer = new HashMap<>(); // 加载xml文件 InputStream is = IOCTest.class.getClassLoader().getResourceAsStream("IOCTest.xml"); // 使用dom4j把文件解析成为dom对象 SAXReader saxReader = new SAXReader(); Document dom = saxReader.read(is); // 通过dom树获得节点标签与属性 Element rootElement = dom.getRootElement(); // 获得所有的标签 List<Element> beanLists = rootElement.elements(); // 创建bean放到实体类中 for (Element item : beanLists) { // 获得每一个节点的id属性与class属性的值 String id = item.attributeValue("id"); String aClass = item.attributeValue("class"); // 通过反射创建对象 Class<?> object = Class.forName(aClass); Object instance = object.newInstance(); // 把创建的对象放置到IOC容器中 IOCContainer.put(id,instance); } // 获得对象 UserService test = (UserService) IOCContainer.get("test"); test.save(); } }
-
Spring实现IOC
-
Spring的IOC的HelloWord
-
引入Spring的依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency>
-
编写配置文件
- 引入配置文件的Schema约束
<?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"></beans>
-
配置创建实体类的全限定类名
<!--配置service--> <bean id="accountService" class="com.wx.service.impl.AccountServiceImpl">
-
获取容器创建的对象
// 加载配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); // 获得bean对象 AccountService accountService = (AccountService) applicationContext.getBean("accountService"); // 调用实体类对象的方法 accountService.saveAccount();
-
bean标签的属性
- id: 每一个实体类的唯一标识,相当于map中的k
- class :让容器托管的实体类的全限定类名 相当于map中的v
- scope: 控制容器产生的对象是单例还是多例
- 属性取值:singletion创建单例对象,prototype 多例
- inite-method
- 在执行完创建实体类的构造方法以后执行的方法
- destroy-methord
- 在容器正常关闭的时候执行的方法
-
BeanFactory和ApplicationContext的区别
- BeanFactory是Spring中IoC容器的顶层接口,而ApplicationContext是它的一个子接口,所以ApplicationContext具备BeanFactory提供的全部功能
- BeanFactory是Spring的IoC基础容器。而ApplicationContext是容器的高级接口,它比BeanFactory多了很多重要的功能。例如,父子容器的概念(在SpringMVC课程中讲解),AOP的支持,消息发布机制,事件处理机制,国际化和资源访问等等
- 创建对象的时间点不一样
- ApplicationContext:只要一读取配置文件, 默认情况下就会创建对象
- BeanFactory:什么使用什么时候创建对象
-
Bean标签的对象获取: getBean方法
- 通过bean标签的id获得
- 通过对象的字节码文件获得
- 如果一个接口有多个实现类,通过id和字节码文件获得
-
bean标签的生命周期
- 如果创建的对象是单例的,与容器的生命周期一样
- 如果是多例的,对象创建完毕以后只能被GC回收
-
-
bean实例化对象的三种方式
- 一:直实例化class指向一个实体类
- 二:通过静态工厂实例化:calss指向静态工厂 factory-methord指向对应对应静态工厂中的方法名
- 三:通过实例工厂实例化:先配置工厂bean class指向实例工厂 配置具体执行bean factory-bean指向实例工厂的id factory-methord指向创建对应实体类的方法名
Spring依赖注入
-
Dependency Injection 依赖注入
-
通过控制反转把创建实体类的权利移交给了IOC容器,在ioc容器进行实例化一个对象的时候需要一些相关的资源通过DI的方式把资源提供给实例化过程中需要使用到这些资源的类
-
依赖注入的方式
-
使用构造函数的方式注入
-
在需要注入资源的类中提供构造方法
-
在bean标签下面使用constructor-arg为构造器传递参数
-
constructor-arg标签的属性如下:
- index:指定构造方法的参数的索引从0开始
- name:构造方法里面参数的名字
- type:构造方法的参数的数据类型
<bean id="accountService" class="com.wx.service.impl.AccountServiceImpl"> <!--根据name方式 ,进行构造方法赋值--> <constructor-arg name="name" value="迪丽热巴"></constructor-arg> <constructor-arg name="age" value="22"></constructor-arg> <constructor-arg name="birthday" ref="myDate"></constructor-arg> <!--根据index方式, 进行构造方法赋值--> <constructor-arg index="0" value="晓明"></constructor-arg> <constructor-arg index="1" value="25"></constructor-arg> <constructor-arg index="2" ref="myDate"></constructor-arg> <!--根据type方式, 进行构造方法赋值--> <constructor-arg type="java.lang.String" value="小丽"></constructor-arg> <constructor-arg type="java.lang.Integer" value="26"></constructor-arg> <constructor-arg type="java.util.Date" ref="myDate"></constructor-arg> </bean>
-
-
使用set方式注入
- 对需要注入的属性添加set方法
- 将要注入的资源申明为bean
- 将要注入的引用类型的变量通过property属性进行注入 name是变量名,[引用类型]ref是属性声明要注入的资源id,非引用类型是使用value属性
<!-- 资源注入--> <bean id="setDi" class="com.wx.services.imp.UserServiceImp"> <!-- 引用类型的set注入--> <property name="stu" ref="student"></property> </bean> <!-- 注入资源的Bean--> <bean id="student" class="com.wx.entity.Student" > <!-- 基本类型的set注入 --> <property name="name" value="测试"></property> </bean>
-
注入属性集合
-
array list set map property五种类型的集合注入
<bean id="collectionDi" class="com.wx.services.imp.UserServiceImp"> <property name="arrsys"> <array> <value>数组注入一</value> <value>数组注入二</value> <value>数组注入三</value> </array> </property> <property name="list"> <list> <value>list集合注入一</value> <value>list集合注入二</value> </list> </property> <property name="set"> <set> <value>set集合注入一</value> <value>set集合注入二</value> </set> </property> <property name="map"> <map> <entry key="001" value="map一"></entry> <entry key="002" value="map二"></entry> </map> </property> <property name="properties"> <props> <prop key="007">pro1</prop> <prop key="008">pro2</prop> </props> </property> </bean>
P命名空间简化配置
-
p命名空间的使用
-
引入schema约束
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
使用 p命名空间给属性赋值(使用的是set赋值的方式)
属性值是基本类型 p:属性名=“值”
属性值是引用类型 p:属性名-ref=“bean的id”
-
-
-
properties文件
-
spring提供了读取外部properties文件的机制,使用读取到的数据为bean赋值
-
使用步骤
-
引入schema约束文件
xmlns:context="http://www.springframework.org/schema/context"
-
加载指定的properties文件
context:property-placeholder location="classpath:filename.properties">
-
使用加载的数据
<property name="接收配置文件的属性名" value="${properties配置文件中的k}"/>
-
在使用properties配置文件的时候k值不要与电脑环境变量中的k冲突在使用spring集成以后会加载电脑中的所有的环境变量,有可能导致value取出来的值不是配置的对应的,而是电脑环境变量中对应的值
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WfBOkksO-1594724197860)(F:\MarkDownOnte\学习笔记\Spring\assets\1594717755052.png)]
多个配置文件的整合
-
标签名称:import
-
属性:标签
-
归属:beans标签
-
作用:在主配置文件中加载其他的配置文件
<import resource="classpath:配置文件名"/>
- 加载properties配置文件在主配置文件中加载,也可以在子配置文件中使用。
第三方bean的配置
- spring是一个综合性的框架,可以在spring里面整合其他的框架,在使用不同的框架的时候有不同的配置文件,在进行整合的时候有两种选择,第一种是保留各自的配置文件,还有就是把被整合的框架的配置文件整合到Spring的配置文件中
可能导致value取出来的值不是配置的对应的,而是电脑环境变量中对应的值
多个配置文件的整合
-
标签名称:import
-
属性:标签
-
归属:beans标签
-
作用:在主配置文件中加载其他的配置文件
<import resource="classpath:配置文件名"/>
- 加载properties配置文件在主配置文件中加载,也可以在子配置文件中使用。
第三方bean的配置
- spring是一个综合性的框架,可以在spring里面整合其他的框架,在使用不同的框架的时候有不同的配置文件,在进行整合的时候有两种选择,第一种是保留各自的配置文件,还有就是把被整合的框架的配置文件整合到Spring的配置文件中