万字Spring框架学习总结(附核心代码详细注释)
Posted ascto
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了万字Spring框架学习总结(附核心代码详细注释)相关的知识,希望对你有一定的参考价值。
Spring学习笔记总结
学习视频地址:动力节点视频
1.Spring概述
1.1Spring框架是什么?
Spring框架是一个开放源代码的J2EE应用程序框架,由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson/1423612)发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。
- spring全家桶: spring ,springmvc,spring boot,spring cloud
- spring:出现是在2002左右,解决企业开发的难度。减轻对项目模块之间的管理,类和类之间的管理,帮 助开发人员创建对象,管理对象之间的关系。spring核心技术ioc ,aop。能实现模块之间,类之间的解耦合。
1.2Spring的优点
-
轻量
spring框架使用的jar比较小,都在1M一下或者几百kb。spring核心功能的所需的jar总共在3M左右。spring框架运行时占用的资源少,运行效率高,不依赖别的jar。
-
针对接口编程,解耦合
spring提供了Ioc控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现状由容器完成。对象之间的依赖解耦合。
-
AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统0OP实现的功能可以通过AOP轻松应付,在Spring中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
-
方便集成各种优秀的框架
Spring不排斥各种优秀的开源框架,相反Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架( 如Struts,Hibernate、MyBatis) 等的直接支持。简化框架的使用。Spring像插线板一样, 其他框架是插头,可以容易的组合到一起。需要使用哪个框架,就把这个插头放入插线板。不需要可以轻易的移除。
1.3Spring的体系结构
2.Ioc控制反转
控制反转(Ioc,Inversion of Control),是一个概念,一种思想。指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值,依赖的管理。
IoC是一个概念,是一种思想,其实现方式多种多样。当前比较流行的实现方式是依赖注入。应用广泛。
依赖: classA 类中含有classB的实例,在classA中调用classB的方法完成功能,即classA对classB有依赖。
loc的实现:
➢依赖注入: DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行完成。
依赖注入DI是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。
Spring的依赖注入对调用者与被调用者几乎没有任何要求,完全支持对象之间依赖关系的管理。
Spring框架使用依赖注入(DI) 实现IoC。
Spring容器是一个超级大工厂,负责创建、管理所有的Java对象,这些Java对象被称为Bean。Spring 容器管理着容器中Bean之间的依赖关系,Spring 使用“依赖注入”的方式来管理Bean之间的依赖关系。使用loC实现对象之间的解耦合。
2.1开发工具准备
利用maven工具,创建
实现步骤:
1.创建maven项目
2.加入maven的依赖
spring的依赖,版本5.3.7
junit依赖
3.创建类(接口和它的实现类),和没有使用框架一样,就是普通的类。
4.创建spring需要使用的配置文件
声明类的信息。这些类由spring创建和管理
5.测试spring创建的对象。
2.2Sprig的第一个程序
<?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,告诉spring要创建某个类的对象
id是对象的自定义名称(唯一值)。spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为spring是反射机制)
spring就完成SomeService someService = new SomeServiceImpl();
spring是把创建好的对象放到了map中,spring框架中有一个map存放对象的。
springMap.put(id的值,对象)
例如 springMap.put("someService",new someServiceImpl());
一个bean标签只声明一个对象
-->
<bean id="someService" class="cqutlc.service.Impl.someServiceImpl"></bean>
<!--spring能创建一个非自定义的类-->
<bean id="mydate" class="java.util.Date"/>
</beans>
<!--spring的配置文件
1.beans是根标签,spring中把Java对象成为bean
2.spring-beans.xsd是约束文件,和mybatis指定的类似
-->
package cqutlc;
import cqutlc.service.Impl.someServiceImpl;
import cqutlc.service.someService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
@Test
public void test1(){
someService someService=new someServiceImpl();
someService.doSome();
}
/*spring默认创建对象的时间:在创建spring的容器时,他会创建配置文件中的所有对象*/
@Test
public void test2(){
//使用spring容器创建的对象
//1.指定spring配置文件的名称
String config="beans.xml";
//2.创建表示spring容器的对象,ApplicationContext
//ClassPathXmlApplicationContext;表示从类路径中加载spring的配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
//3.从容器中获取某个对象,你要调用对象的方法,
//getBean("配置文件中的bena的id值");
someService service=(someService)ac.getBean("someService");
//使用spring创建好的对象
service.doSome();
}
/*获取spring容器中的Java对象的信息*/
@Test
public void test3(){
String config="beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
//使用spring提供的方法,获取容器中定义的对象的数量
int num=ac.getBeanDefinitionCount();
System.out.println(num);
//容器中每个定义的对象的名称
String[] names= ac.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
2.3基于XML的DI
在spring配置文件中,给Java对象的属性赋值。
di:依赖注入,表示创建对象,给属性赋值。
di的实现语法:
1.在spring配置文件中,使用标签和属性完成,叫做基于xml的di实现
2.使用spring中的注解进行属性的赋值,叫做基于注解的di实现。
di的语法分类
1.set注入(设置注入): spring调用类的set方法,在set方法可以实现属性的赋值
2.构造注入,spring调用类的有参构造方法,创建对象。在构造方法中完成赋值。
set注入实例分析
<?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">
<!--声明student对象
注入:就是赋值的意思
简单类型:spring中规定Java的基本数据类型和string类型都是简单类型。
di:给属性赋值
1.set注入(设置注入):spring调用类的set方法,你可以在set方法中完成属性赋值
利用property
-->
<bean id="student" class="cqutlc.ba01.Student">
<property name="name" value="李四"/><!--调用setName...-->
<property name="age" value="20"/>认准set方法
</bean>
</beans>
当属性为引用类型时
2.引用类型的set注入:spring调用set方法
-->
<bean id="student" class="cqutlc.ba02.Student">
<property name="name" value="李四"/><!--调用setName...-->
<property name="age" value="24"/>
<property name="school" ref="school"/>
</bean>
<bean id="school" class="cqutlc.ba02.School">
<property name="name" value="cqut"/>
<property name="address" value="cq"/>
</bean>
构造注入
得有构造参数
2.构造注入 spring调用类的有参数构造方法,在创建对象的同时给属性赋值
构造注入使用
-->
<bean id="student" class="cqutlc.ba03.Student">
<constructor-arg name="name" value="lc"/>
<constructor-arg name="age" value="19"/>
<constructor-arg name="school" ref="myschool"/>
</bean>
<bean id="myschool" class="cqutlc.ba03.School">
<property name="name" value="cqut"/>
<property name="address" value="cq"/>
</bean>
引用类型的自动注入
byName和byType
<?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框架根据某些规则可以给引用类型赋值。不用你再给引用类型赋值了
使用的规则常用的是
1.byName(按名称注入):Java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样。
且数据类型一致,这样的容器中的bean,spring能够赋值给引用类型。
2.byType(按类型注入):Java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class是同源关系。
<bean id="" class="" outowire="byType">
-->
<bean id="student" class="cqutlc.ba04.Student" autowire="byName">
<property name="name" value="李四"/><!--调用setName...-->
<property name="age" value="24"/>
<!--<property name="school" ref="school"/>-->
</bean>
<bean id="school" class="cqutlc.ba04.School">
<property name="name" value="cqut"/>
<property name="address" value="cq"/>
</bean>
</beans>
多个配置文件的优势
1.每个文件的大小比一个文件要小得多。效率高
2.避免多人竞争带来的冲突
多文件的分配方式:
1.按功能模块,一个模块一个配置文件。
2.按类的功能,数据库相关,做事务处理的,做service的。
包含关系的配置路径
2.4基于注解的DI
通过注解完成Java对象的创建,属性赋值
使用注解的步骤
-
加入maven的依赖spring-context,在你加入spring-context的同时,间接加入spring-aop的依赖。
使用注解必须使用spring-aop依赖
-
在类中加入spring的注解(多个不同功能的注解)
-
在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置。
学习的注解有:
1.@Component 2.@Repository 3.@Service 4.@Controller 5.@Value 6.@Autowired 7.@Resource
简单类型
<?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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--声明组件扫描器(component-scan),
组件就是Java对象,所以就是找Java对象
base-package:指定注解在你的项目中的包名
component-scan工作方式:spring会扫描遍历base-package指定的包
把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象和给属性赋值。
-->
<context:component-scan base-package="cqutlc.ba01"/>
</beans>
package cqutlc.ba01;
import org.springframework.stereotype.Component;
/*
* @Component:创建对象的,等同于<bean>的功能
* 属性value: 就是对象的名称,也就是bean的id值,value值是唯一的,创建的对象在整个spring容器中就一个
* 位置:在类的上面写注解
* */
//等同于<bean id="myStudent" class="cqutlc.ba01.Student"/>
//@Component(value = "myStudent")
//省略value
//@Component("myStudent")
//不指定对象名称,由spring提供默认名称(首字母小写类名)
@Component
public class Student {
private String name;
private Integer age;
public void setName (String name) {
this.name = name;
}
public void setAge (Integer age) {
this.age = age;
}
@Override
public String toString () {
return "Student{" +
"name='" + name + '\\'' +
", age=" + age +
'}';
}
}
package cqutlc;
import cqutlc.ba01.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test1 {
@Test
public void test(){
String config="applicationContext.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext (config);
//从容器中获取对象
Student student=(Student) ac.getBean ("student");
System.out.println (student);
}
}
* spring中和@Component功能一致,创建对象的注解还有:
* @Repository(用在持久层上):放在dao的实现类上面,
* 表示创建dao对象,dao对象是能访问数据库的。(持久层注解)
*
* @Service(用在业务层类的上面):放在service的实现类上面,
* 创建service对象,service对象是做业务处理的,可以有事物等功能的。
*
* @Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,
* 控制器对象可以接收用户提交的参数和显示请求的处理结果。
*
* 以上三个注解的使用语法和@Component是一样的,都能够创建对象,但是这三个注解还有额外的功能----给项目分层
指定多个包的三种方式
- 使用多次组件扫描器标签,指定不同的包
- 使用分隔符(分号或者逗号)分隔多个包名
- 指定父包
引用类型
@Autowired:spring框架提供的注解,实现引用类型的赋值
spring中通过注解给引用类型赋值,使用的是自动注入,支持byName和byType
@Autowired默认使用@byType自动注入
位置:1.在属性定义的上面,无需set方法,推荐使用。被引用的类必须提前利用@Component注解标识。
2.在set方法的上面
属性:required,是一个boolean类型的,默认是true,表示引用类型失败时,程序报错并终止运行。要是false则正常运行,赋值为null
最好用true,可以及时发现错误!
如果要使用byName的方式
1.在属性的上面加上@Autowired
2.在属性上面加入@Qualifier(vlaue=“bean的id”):表示使用指定名字的bean完成赋值。
@Resource:来自于JDK中的注解,spring框架提供了对这个注解功能的支持。可以用它给引用类型赋值,使用的也是自动注入原理,支持byName,byType。默认是byName
位置:
1.在属性定义的上面,无需set方法,推荐使用
2.在set方法的上面 先使用byName自动注入,假如失败了就会再使用byType
如何只使用byName?
需要新增加一个属性name name的值为bean的id名称
3.AOP面向切面编程
3.1动态代理
动态代理是指:程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理只是由代理生成工具(不是真实定义的类)在程序运行时由JVM根据反射等机制动态生成,代理对象与目标对象的代理关系在程序运行时确定。
实现方式:
jdk动态代理, 使用jdk中的Proxy, Method, Invocai tonHanderl创建代理对象。jdk动态代理要求目标类必须实现接口。
cglib动态代理:第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类。子类就是代理对象。要求目标类不能是final的,方法也不能是final的。
动态代理的作用:
- 在目标类源代码不变的情况下,增强功能
- 减少代码的重复
- 专注业务逻辑代码
- 解耦合,让你的业务功能和日志,事务非事务功能分离
3.2AOP简介
AOP (Aspect Orient Programming),面向切面编程。面向切面编程是从动态角度考虑程序运行过程。
AOP底层,就是采用动态代理模式实现的。采用了两种代理: JDK的动态代理,与CGLIB的动态代理。
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,可通过运行期动态代理实现程序功能的统一维护的一种技术。AOP是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。(动态代理的规范化,把动态代理的实现步骤,方式都定义好了,让开发人员用一种统一的方法,使用动态代理)。
切面:给你的目标类增加的功能,就是切面,什么日志等(切面的特点:一般都是非业务方法,独立使用的。)
面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP容器的功能将切面织入到主业务逻辑中。所谓交叉业务逻辑是指,通用的、与主业务逻辑无关的代码,如安全检查、事务、日志、缓存等。
若不使用AOP,则会出现代码纠缠,即交叉业务逻辑与主业务逻辑混合在一起。这样,会使主业务逻辑变的混杂不清。
如何理解面向切面编程?
- 需要在分析项目功能时,找出切面。
- 合理的安排切面的执行时间(在目标方法前呢,还是后呢)
- 合理的安全切面执行位置,在哪个类,哪个方法增加增强
3.3AOP编程术语
- Aspect:切面,表示增强的功能,就是一堆代码,完成某个功能。(非业务功能,可独立执行。如:日志,统计信息,权限验证等)
- JoinPoint:连接点,连接你的业务方法和切面位置。其实就是某个类中的业务方法。
- Pointcut:切入点,指多个连接点方法的集合。
- 目标对象:给哪个类的方法增加功能,这个类就是目标对象。
- Advice:通知,通知表示切面功能执行的时间。
一个切面有三个关键的要素:
- 切面的功能代码,切面干什么
- 切面的执行位置,使用Pointcut表示切面执行位置
- 切面执行时间,使用advice表示时间。
3.4AspectJ对AOP的实现
aop的实现
aop是一个规范,是一个动态的一个规范化,一个标准。
aop的技术实现框架:
1.spring:spring在内部实现了aop规范,能做aop的工作。
2.aspectJ:一个开源的专门做aop的框架。spring框架中集成了aspectJ框架,通过spring就可以使用aspectJ的功能了。
aspectJ框架实现有两种方式:1.使用xml的配置文件(配置全局事务) 2.使用注解,一般都用注解
3.5学习AspectJ框架的使用
如何表示切面的执行时间?
注解表示:1.@Before 2.@AfterReturning 3.@Around 4.@AfterThrowing 5.@After
如何表示切面执行的位置?
使用的是切入点表达式。
表达式原型为:
execution(modifiers-pattern? ret-type-pattern
declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
解释:
modifiers-pattern 访问权限类型
ret-type-pattern 返回值类型
declaring-type-pattern 包名类名
name-pattern(param-pattern) 方法名(参数类型和参数个数)
throws-pattern 抛出异常类型
?表示可选部分
以上表达式共分为四个部分 execution(访问权限 方法返回值 方法声明(参数)异常类型)
切入点表达式要匹配的对象就是目标方法的方法名。所以,execution 表达式中明显就是方法的签名。注意,表达式中黑色文字表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:
Aspect的开发环境
使用aspectJ框架实现aop
使用aop:目的是给已经存在的一些类和方法,增加额外的功能,前提是不改变原来的类的代码。
框架的使用步骤:
1.新建maven项目
2.加入依赖
spring依赖 aspectJ依赖 junit单元测试
3.创建目标类:接口和他的实现类
要做的是给类中的方法去增加功能
4.创建切面类:普通类
1.在类的上面加入@Aspect
2.在类中去定义方法---要执行的功能代码
3.在方法的上面加入aspectJ中的通知注解,例如@Before
还需要指定切入点表达式execution()
5.创建spring的配置文件,在文件中声明对象,把对象交给容器统一管理
声明对象可以使用注解或者xml配置文件
声明目标对象
声明切面类对象
声明aspectJ框架中的自动代理生成器标签(用来完成代理对象的自动创建功能的)
6.创建测试类,从spring容器中获取目标对象(实际上是代理对象)。
通过代理执行方法,实现aop的功能增强
@Before实现的一个例子
package cqutlc.ba01;
public interface SomeSevice {
void doSome(String name,Integer age);
}
package cqutlc.ba01;
//目标类
public class SomeSeviceImpl implements SomeSevice {
@Override
public void doSome (String name, Integer age) {
//给doSome方法增加一个功能,在doSome方法执行之前,输出方法的执行时间
System.out.println ("目标方法执行");
}
}
package cqutlc.ba01;
import org.aspectj.lang.annotation.Aspect;
import org.以上是关于万字Spring框架学习总结(附核心代码详细注释)的主要内容,如果未能解决你的问题,请参考以下文章
Hive从入门到精通,HQL硬核整理四万字,全面总结,附详细解析,赶紧收藏吧!!
一篇文零基础带你搞懂回溯(万字:核心思维+图解+习题+题解思路+代码注释)
SSM(Spring+SpringMVC+Mybatis)框架搭建详细教程附源代码Demo