当前位置: 首页 > article >正文

快速了解Spring(超详细+干货满满)

spring的概念

在不同的语境中,Spring 所代表的含义是不同的。下面我们就分别从“广义”和“狭义”两个角度,对 Spring 进行介绍。

广义的 Spring --> Spring 技术栈

广义上的 Spring 泛指以 Spring Framework 为核心的 Spring 技术栈

经过十多年的发展,Spring 已经不再是一个单纯的应用框架,而是逐渐发展成为一个由多个不同子项目(模块)组成的成熟技术,例如 Spring Framework、Spring MVC、SpringBoot、Spring Cloud、Spring Data、Spring Security 等,其中 Spring Framework 是其他子项目的基础

这些子项目涵盖了从企业级应用开发到云计算等各方面的内容,能够帮助开发人员解决软件发展过程中不断产生的各种实际问题,给开发人员带来了更好的开发体验。

狭义的 Spring --> Spring Framework

狭义的 Spring 特指 Spring Framework,通常我们将它称为 Spring 框架。

Spring 框架是一个分层的、面向切面的 Java 应用程序的一站式轻量级解决方案,它是 Spring 技术栈的核心和基础,是为了解决企业级应用开发的复杂性而创建的。

Spring 有两个最核心模块: IOC 和 AOP

IOC:Inverse of Control 的简写,译为“控制反转”,指把创建对象过程交给 Spring 进行管理。

AOP:Aspect Oriented Programming 的简写,译为“面向切面编程”。AOP 用来封装多个类的公共行为,将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,减少系统的重复代码,降低模块间的耦合度。另外,AOP 还解决一些系统层面上的问题,比如日志、事务、权限等。

案例引入并思考

<dependencies><!--spring context依赖--><!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.2</version></dependency><!--junit5测试--><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.3.1</version></dependency>
</dependencies>
package com.atguigu.spring6.bean;public class HelloWorld {public void sayHello(){System.out.println("helloworld");}
}
<?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"><!--配置HelloWorld所对应的bean,即将HelloWorld的对象交给Spring的IOC容器管理通过bean标签配置IOC容器所管理的bean属性:id:设置bean的唯一标识class:设置bean所对应类型的全类名--><bean id="helloWorld" class="com.atguigu.spring6.bean.HelloWorld"></bean></beans>
package com.atguigu.spring6.bean;import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class HelloWorldTest {@Testpublic void testHelloWorld(){ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");HelloWorld helloworld = (HelloWorld) ac.getBean("helloWorld");helloworld.sayHello();}
}

 思考

1.测试得知:创建对象的时候确实调用了无参构造的方法2.如何使用返回创建的对象?
2.1 加载bean.xml配置文件
2.2 对xml文件进行解析操作
2.3 获取xml文件bean标签属性值:id属性值和class属性值
2.4 使用反射根据类全路径创建对象
 // dom4j解析beans.xml文件,从中获取class属性值,类的全类名// 通过反射机制调用无参数构造方法创建对象Class clazz = Class.forName("com.atguigu.spring6.bean.HelloWorld");//Object obj = clazz.newInstance();Object object = clazz.getDeclaredConstructor().newInstance();
//bean对象最终存储在spring容器中,在spring源码底层就是一个map集合,存储bean的map在DefaultListableBeanFactory类中:
private final Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);//Spring容器加载到Bean类时,会把这个类的描述信息, 以包名加类名的方式存到beanDefinitionMap中
//Map<String,BeanDefinition>,其中String是Key,默认是类名首字母小写,BeanDefinition存的是类的定义(描述信息),我们通常叫BeanDefinition接口为:bean的定义对象。

容器IOC

  1. IOC 是 Inversion of Control 的简写,译为"控制反转"
  2. Spring通过IOC容器来管理所有java对象的实例化和初始化,控制对象与对象之间的依赖关系,我们将由IOC容器管理的java对象称为Spring Bean,它与使用关键字new创建的java对象没有任何区别
  3. IOC容器是spring框架中最重要的核心组件之一,它贯穿了spring从诞生到成长的整个过程
  4. 控制反转:控制反转是一种思想,靠DI(依赖注入)来实现,目的为了降低程序耦合度,提高程序扩展力,将对象的创建权利交出去,交给第三方容器负责,将对象和对象之间关系的维护权交出去,交给第三方容器负责
  5. BeanDefinition:Bean定义信息
  6. BeanDefinitionReader:抽象接口
  7. DI:依赖注入,依赖注入实现了控制反转的思想,依赖注入指Spring创建对象的过程中,将对象依赖属性通过配置进行注入,常见的实现方式:1.set注入, 2.构造注入所以结论是IOC就是一种控制反转的思想,而DI是对IOC的一种具体实现
  8. Bean管理说的是,Bean对象的创建,以及Bean对象中属性的赋值(或者叫Bean对象之间关系的维护)

IOC容器在Spring的实现

  1. BeanFactory这是IOC容器的基本实现,是Spring内部使用的接口
  2. ApplicationContextBeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用 ApplicationContext 而不是底层的 BeanFactory

类型名

简介

ClassPathXmlApplicationContext

通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象

FileSystemXmlApplicationContext

通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象

ConfigurableApplicationContext

ApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的能力。

WebApplicationContext

专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中。

基于XML管理bean

获取bean的方式根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象 instanceof 指定的类型』的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。java中instanceof运算符用于判断前面的对象是否是后面的类,或其子类、实现类的实例。如果是返回true,否则返回false。也就是说:用instanceof关键字做判断时, instanceof 操作符的左右操作必须有继承或实现关系

<bean id="studentOne" class="com.atguigu.spring6.bean.Student"><!-- property标签:通过组件类的setXxx()方法给组件对象设置属性 --><!-- name属性:指定属性名(这个属性名是getXxx()、setXxx()方法定义的,和成员变量无关) --><!-- value属性:指定属性值 --><property name="id" value="1001"></property><property name="name" value="张三"></property><property name="age" value="23"></property><property name="sex" value="男"></property>
</bean>Test:
@Test
public void testDIBySet(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring-di.xml");Student studentOne = ac.getBean("studentOne", Student.class);System.out.println(studentOne);
}
<bean id="studentTwo" class="com.atguigu.spring6.bean.Student"><constructor-arg value="1002"></constructor-arg><constructor-arg value="李四"></constructor-arg><constructor-arg value="33"></constructor-arg><constructor-arg value="女"></constructor-arg>
</bean>
constructor-arg标签还有两个属性可以进一步描述构造器参数:- index属性:指定参数所在位置的索引(从0开始)
- name属性:指定参数名Test:
@Test
public void testDIByConstructor(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring-di.xml");Student studentOne = ac.getBean("studentTwo", Student.class);System.out.println(studentOne);
}
1.字面值赋值
<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/>2.null值
<property name="name"><null />
</property>3.xml实体
<!-- 小于号在XML文档中用来定义标签的开始,不能随便使用 -->
<!-- 解决方案一:使用XML实体来代替 -->
<property name="expression" value="a &lt; b"/>4.CDATA节
<property name="expression"><!-- 解决方案二:使用CDATA节 --><!-- CDATA中的C代表Character,是文本、字符的含义,CDATA就表示纯文本数据 --><!-- XML解析器看到CDATA节就知道这里是纯文本,就不会当作XML标签或属性来解析 --><!-- 所以CDATA节中写什么符号都随意 --><value><![CDATA[a < b]]></value>
</property>
方式一:直接引用
<bean id="clazzOne" class="com.atguigu.spring6.bean.Clazz"><property name="clazzId" value="1111"></property><property name="clazzName" value="财源滚滚班"></property>
</bean><bean id="studentFour" class="com.atguigu.spring6.bean.Student"><property name="id" value="1004"></property><property name="name" value="赵六"></property><property name="age" value="26"></property><property name="sex" value="女"></property><!-- ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值 --><property name="clazz" ref="clazzOne"></property>
</bean>方式二:内部bean
<bean id="studentFour" class="com.atguigu.spring6.bean.Student"><property name="id" value="1004"></property><property name="name" value="赵六"></property><property name="age" value="26"></property><property name="sex" value="女"></property><property name="clazz"><!-- 在一个bean中再声明一个bean就是内部bean --><!-- 内部bean只能用于给属性赋值,不能在外部通过IOC容器获取,因此可以省略id属性 --><bean id="clazzInner" class="com.atguigu.spring6.bean.Clazz"><property name="clazzId" value="2222"></property><property name="clazzName" value="远大前程班"></property></bean></property>
</bean>方式三:级联属性赋值
<bean id="studentFour" class="com.atguigu.spring6.bean.Student"><property name="id" value="1004"></property><property name="name" value="赵六"></property><property name="age" value="26"></property><property name="sex" value="女"></property><property name="clazz" ref="clazzOne"></property><property name="clazz.clazzId" value="3333"></property><property name="clazz.clazzName" value="最强王者班"></property>
</bean>
//使用util:list、util:map标签必须引入相应的命名空间
<?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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
//引入p命名空间
<?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:util="http://www.springframework.org/schema/util"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">//引入p命名空间后,可以通过以下方式为bean的各个属性赋值
<bean id="studentSix" class="com.atguigu.spring6.bean.Student"p:id="1006" p:name="小明" p:clazz-ref="clazzOne" p:teacherMap-ref="teacherMap"></bean>

基于注解管理bean

//@Resource和@Autowired的区别
@Resource注解是JDK扩展包中的,也就是说属于JDK的一部分,该注解是标准注解,更加具有通用性
@Autowired注解是Spring框架的
@Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name,通过byName找不到的话会自动启动通过类型byType装配
@Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用
<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>

 bean的生命周期

参考文章:一文读懂 Spring Bean 的生命周期_spring bean的生命周期-CSDN博客

 Log4fj2日志框架

日志信息的优先级,日志信息的优先级从高到低有TRACE < DEBUG < INFO < WARN < ERROR < FATAL TRACE:追踪,是最低的日志级别,相当于追踪程序的执行 
DEBUG:调试,一般在开发中,都将其设置为最低的日志级别 
INFO:信息,输出重要的信息,使用较多 
WARN:警告,输出警告的信息 
ERROR:错误,输出错误信息 
FATAL:严重错误这些级别分别用来指定这条日志信息的重要程度
级别高的会自动屏蔽级别低的日志,也就是说,设置了WARN的日志,则INFO、DEBUG的日志级别的日志不会显示
日志信息的输出目的地指定了日志将打印到控制台还是文件中
日志信息的输出格式控制了日志信息的显示内容
<!--log4j2的依赖-->
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.19.0</version>
</dependency>
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.19.0</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<configuration><loggers><!--level指定日志级别,从低到高的优先级:TRACE < DEBUG < INFO < WARN < ERROR < FATALtrace:追踪,是最低的日志级别,相当于追踪程序的执行debug:调试,一般在开发中,都将其设置为最低的日志级别info:信息,输出重要的信息,使用较多warn:警告,输出警告的信息error:错误,输出错误信息fatal:严重错误--><root level="DEBUG"><appender-ref ref="spring6log"/><appender-ref ref="RollingFile"/><appender-ref ref="log"/></root></loggers><appenders><!--输出日志信息到控制台--><console name="spring6log" target="SYSTEM_OUT"><!--控制日志输出的格式--><PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/></console><!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用--><File name="log" fileName="d:/spring6_log/test.log" append="false"><PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/></File><!-- 这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--><RollingFile name="RollingFile" fileName="d:/spring6_log/app.log"filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"><PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/><SizeBasedTriggeringPolicy size="50MB"/><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 --><DefaultRolloverStrategy max="20"/></RollingFile></appenders>
</configuration>

http://www.lryc.cn/news/2417638.html

相关文章:

  • 【TS】2134- 重新学习 TypeScript 类型系统
  • ce Cheat Engine 环境搭建
  • Nopepad++使用教程
  • 深入理解Electron一Electron架构介绍
  • Elasticsearch-基础介绍及索引原理分析
  • VMware16Pro虚拟机安装教程(超详细)
  • python下载安装教程电脑版,Python下载安装后找不到
  • 使用MobaXterm ssh免密远程连接虚拟机
  • WEPE系统安装纯净版window11教程(包含pe内系统安装方法)
  • 【Unity3D】Unity3D学习笔记
  • 最新Node.js安装详细教程及node.js配置
  • base64编码解码器【C++】
  • Git指南(一)
  • IDE开发工具Idea使用
  • mysql知识点详细总结
  • 算法笔记(一)—— KMP算法练习题
  • vue-必备知识点,图文详解
  • VSCode初级使用教程详细版
  • 科技概念/名词解释
  • 计算机毕设ssm基于BS的高校学生毕业去向管理系统的设计与实现3l47e9(源码+数据库+LW)
  • 多吉搜索不能用了_百度搜索骚技巧,瞬间找到你想要的资源
  • 关于调用静态链接库LIB,提示重定义或库冲突的错误
  • saltstack-redhat6.5版本
  • 难倒了N个硕士和博士的三年级奥数题
  • 博客(Blog)的商业价值实现模式探讨
  • 使用hydra离线破解windows密码
  • 在Windows中使用TCP端口139和445
  • InfoQ-China发布在即,敬请关注支持
  • HttpServletRequest和ServletRequest的区别以及HttpServletRequest对象方法的用法
  • 【Consul】Consul的Linux之旅:实现高效部署与维护的入门指南