引言
虽然使用SpringBoot架构的过程中非常简单方便,不需要配置那么多的config文件,但是还是要去深入了解和学习其先驱Spring。在这里纪录自己手打稿及对Spring的理解的知识笔记
Spring是什么
它是一个开源框架,为了解决企业应用开发的复杂性而创建的,Spring是一个轻量级的**控制反转**(IoC)和**面向切面**的(AOP)的容器框架。
在其诞生刚开始,创建Spring的主要目的是用来替代更加重量级的企业级Java技术,尤其是EJB。Enterprise Java Beans技术的简称, 又被称为企业Java Beans。相对于EJB来说,Spring提供了更加轻量级和简单的编程模型。它增强了简单老式Java对象(Plain Old Java object,POJO)的功能,使其具备了之前只有EJB和其他企业级Java 规范才具有的功能。总而言之,就是为了简化实现复杂度而诞生。
控制反转(IoC)
什么是控制反转,就是把控制权交出去,在使用的过程中,直接得到对象。**使用控制反转的技术达到松耦合的目的**。例子: 现实例子,我们要建房子,但房子不是我们去设计搭建,而是由开发商来进行搭建,我们通过中介去购买搭建好的房子,在spring中,我们不去创建类,而是由spring容器创建,我们要使用类时,从容器中拿来即可。
面向切面编程(AOP)
允许通过分离应用的业务逻辑与系统服务进行内聚性的开发。
1.业务逻辑: 比如 仓库管理系统中的 商品管理模块
2.系统服务:也就是 在操作的过程中系统纪录一些日志,或者向服务器存储文件之类的系统后台操作。
Spring优点:
1.简单、快捷、方便
2.Spring 带来了复杂的JavaEE开发的春天。
Spring FrameWork Rntime
Spring framework Runtime各层介绍,如上图:
1)、Test: Spring提供测试功能
2)、[Spring核心包]Core Container:Spring核心容器,Spring启动的基本条件:
1. Beans:负责Spring的创建类,对象,管理对象包
2. Core:Spring核心类,用来支持Spring架构的运行
3. Context:上下文参数,获取外部资源,管理注解等
4. SpEL(expression.jar包):SpEL表达式语言包,是一种可以与基于Spring 运行时对象交互的东西。类似于ognl表达式。(Object-Graph Navigation Language的简称),对象图导航语言,它是一门表达式语言,除了用来 设置 和获取Java对象的属性之外,另外提供诸如集合的投影和过滤 以及lambda表达式等,简单来说就是可以用表达式来简化开发,减 少一些逻辑和配置
3)、
AOP: 实现AOP功能需要的依赖
Aspects: 切面AOP依赖包。 也是框架整合包
Instrumentation:Spring 对服务器的代理接口
Messaging: 信息体系结构和协议支持
4)、Data Access/Integration:封装数据访问层相关内容
JDBC: Spring对JDBC封装后的代码
ORM:封装了持久层框架的代码。如Hibernate
transactions:对应spring-tx.jar 声明时事务使用
OXM:Spring对于object/xml映射的支持,可以让JAVA与XML之间来回切换
JMS:为简化jms api的使用而做的简单封装
5)、WEB:需要Spring完成web相关功能时需要
例如:由tomcat加载Spring配置文件时需要有 spring-web包
websocket: sockjs WebSocket的实现,包括对 STOMP的支持
二、Spring作用
Spring是一个容器,其提供了对多种技术的支持,例如ElasticSearch,ShardingJDBC,ActiveMQ, JMS,消息日志Redis等。在使用Spring的过程中,对AOP(事务管理、日志等)的使用是比较多的。
三、Spring架构适用范围
1.构建企业的应用:
SpringMVC
+ Spring
+ Hibernate
+ ibatis
2.单独使用Bean容器,对Bean进行管理
3.单独使用AOP进行切面处理
4.其他的Spring功能,比如: 对消息的支持,RSS订阅
5.在互联网中的应用,比如构建一个电子商城网站,其中Spring可以用来做后台架构。
接口
定义: 用于沟通的中介物的抽象化,比如说你要买房,此时中介和卖房的人就相当于接口,将你的买房请求传达给接口,接口可以获取你的信息并且处理你的请求,但是内部怎么实现的它是不公开的,你只需要告诉接口买什么样的房和条件等,接口会接收你的要求进行处理并且返回信息给你。
值得注意的是: 接口可以支持多重继承,但类不可以,抽象类也不可以。
面向接口编程
结构设计中,分清层次以及调用的关系,每层只向外提供一组功能接口,各层之间仅依赖接口而不是实现类。
举个很简单的例子:
现有接口InterFaceA.java
interface InterFaceA{
String toUpperCase(String str);
}
现有接口InterFaceB 实现A InterFaceB.java
class InterFaceB implements InterFaceA{
@Override
String toUpperCase(String str){
Return str.toUpperCase();
}
}
此时我们新建个测试类:
class test{
public static void main(String[] args){
InterFaceB interFaceB = new InterFaceB ();
System.out.println(interFaceB.toUpperCase(“Hello,World”));
}
}
此时控制台输出为HELLOWORLD.实现了面向接口的编程.
控制反转(IOC)
上图为Spring官网给出的IOC容器的说明:
我们业务的对象进入到容器(POJOS),在Container中,通过配置的元数据,进行生产出符合使用结果的产品。
是什么方面的控制被反转了呢?
获得依赖对象的过程被反转了。也就是说,获得依赖对象不是由我们来获得了,而是由外部容器来获得。
依赖注入(DI)
其实依赖注入就是控制反转。在控制被反转之后,获得依赖对象的过程由自身管理变成了由IOC容器主动注入。这个过程用依赖注入来形容更合适。
怎么实现IOC
IOC容器在初始化的时候,会创建一系列的对象。同时,它能够把这些对象之间的关系通过依赖注入(DI 也称为dependency injection)组织起来。实现IOC的方法就是注入,就是由IOC容器在运行期间,动态的将某种依赖关系注入到对象中。
在IOC容器中,把所有容器的对象都称之为Bean。
如何在Spring配置上面的实例的接口
我们可以通过xml或者注解的方式来配置接口。
在这里,先通过xml的方式进行配置接口 ,大致如下:
<xml version = “1.0” encoding = “UTF-8”>
<beans ...>
<bean id = “toUpperCase” class=”com.example.interface.InterFaceB”>
</bean>
</beans>
注册好后,可以在刚才的测试类中替换如下等同功能代码:
class test{
public static void main(String[] args){
//替换的代码,此时不需要创建实例化对象
InterFaceB interFaceB = super.getBean(‘toUpperCase’);
System.out.println(interFaceB.toUpperCase(“Hello,World”));
}
}
Bean容器的初始化
所初始化需要两个包:
一个是org.springframework.beans
一个是org.springframework.context
上述beans包中的BeanFactory的功能主要是提供配置结构和基本功能,加载并初始化Bean。
而context呢,主要是ApplicationContext保存了Bean对象并在Spring中广泛的被使用。
因此,Bean的初始化有三种方式
1.通过文件的方式来初始化
FileSystemApplicationContext fileSystemApplicationContext =
new FileSystemApplicationContext(“A://java//appcontext.xml”);
2.通过ClassPath的方式来初始化
ClassPathApplicationContext classPathApplicationContext = new
ClassPathApplicationContext(“classpath*:spring-ioc.xml”);
3.通过Web应用的方式来进行初始化
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name> context </servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class
<load-on-startup>l</load-on-startup>
</servlet>
单元测试类的使用
package com.xzsd.pc.jnuit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
@RunWith(BlockJUnit4ClassRunner.class)
public class TestCode extends UnitTestBase{
public TestCode(){
super("classpath*:spring-ioc.xml");
}
@Test
public void testUpper(){
InterFaceB interFaceB = super.getBean("toUpperCase");
System.out.println(interFaceB.toUpperCase("Hello,World"));
}
}
Spring注入
什么是Spring的注入:
通过上面的学习,我们已经知道了Bean注入,IOC注入。Spring注入呢,是值在启动Spring容器的时候,在其加载Bean配置的时候,完成对变量的赋值的过程。
注入的方式有两种:
1.设值注入
也就是通过 set 方法来进行注入。
举例子:
<?xml version= "1.0",encoding= "UTF-8">
-<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www. w3.org/2001/XMLSchema-instancea"
xsi:schemaLocation= " http://www,springframework.org/schema/beans"
"http://www.$pringframework.org/schema/beans/$pring-beans">
<bean id= "injectionA" class= "xzsd.injection.service.InjectionServiceImpl">
<property name= "injection" rel = "injectionDAO"/>
</bean>
<bean id= "inJectionDAO" class= "xzsd.iocJnjection.dao.lnjectionDAOl"> </bean>
</beans>
上面呢,在bean对象中,通过设置property来对成员的属性进行设置,相当于一个类里面的一个属性的 set方法。
2.构造注入
跟上面使用设值注入属性property并不同的是,构造注入使用constructor-arg 来进行注入。
<constructor-arg name= "injection" rel="injectionDAO"/>