赞
踩
Spring 是一套广泛应用于 Java 企业级应用开发领域的轻量级开源框架,由 Rod Johnson 创立,旨在显著降低 Java 企业应用的复杂性,缩短开发周期,并提升开发效率。Spring 不仅适用于服务器端开发,也因其简单的设计、卓越的可测试性和倡导的松耦合原则,使得几乎所有类型的 Java 应用都能从中获得好处。
Spring 框架的核心价值在于提供了诸如控制反转(IoC)、面向切面编程(AOP)等机制,增强了代码的可维护性和可扩展性,并且集成了众多第三方库和框架,如数据库访问、事务管理、MVC、RESTful API 构建、安全控制等,从而形成了一个全方位的企业级应用开发解决方案。
随着版本的不断迭代升级,Spring 已发展到第 6 个主要版本——Spring 6.1.4,这个版本代表了 Spring 团队在响应式编程、模块化支持、性能优化、以及与现代 Java 和云原生环境兼容等方面的最新成果。
须知:现在是更新到了6.1.4,该笔记是基于尚硅谷的6.0.2
在不同的语境中,Spring 所代表的含义是不同的。
广义的 Spring:Spring 技术生态体系
在广义上,Spring 指的是围绕 Spring Framework 扩展建立的一个庞大的技术生态系统,其中包括多个紧密关联的子项目或模块。这个技术栈致力于满足不同层次的开发需求,例如 Web 开发(Spring MVC)、快速应用搭建(Spring Boot)、分布式服务治理(Spring Cloud)、数据访问抽象(Spring Data)、安全控制(Spring Security)等等。每一个子项目都基于 Spring Framework 的核心能力进行构建,为开发者提供了从基础架构到高级应用场景的一整套解决方案。
狭义的 Spring:Spring Framework
狭义上的 Spring 即 Spring Framework,这是整个 Spring 生态系统的核心部分,通常我们称之为 Spring 框架。它是一种轻量级的 Java 应用开发框架,通过提供 IoC(控制反转)和 AOP(面向切面编程)两大核心技术,简化了企业级应用的复杂性,提升了开发效率。
总结简单解释就是
广义的 Spring可以理解为一个完整的 Java 技术生态系统,包括一系列由 Spring 团队开发和维护的子项目,这些项目各具特色,互相配合,共同服务于企业级应用的开发全过程,从基础的依赖注入、面向切面编程,到 Web 开发、微服务架构、数据访问、安全性控制等方面均有覆盖,极大地方便了开发者构建高质量、高效率的软件系统。
狭义的 Spring则特指 Spring Framework 这一具体框架,它是整个 Spring 生态系统的基石。Spring Framework 通过实现控制反转(IoC)来解耦组件之间的依赖关系,让代码更加灵活易管理;同时,它引入了面向切面编程(AOP)机制,使得开发者能方便地在系统中定义和应用横切关注点,如日志、事务管理等,进而增强代码复用性和系统可维护性。
Spring Framework 的五大特点:
官网地址:Spring | Home
上图中包含了 Spring 框架的所有模块,这些模块可以满足一切企业级应用开发的需求,在开发过程中可以根据需求有选择性地使用所需要的模块。下面分别对这些模块的作用进行简单介绍。
注:我自己笔记上面演示的IDEA版本是2023.3.3,也是我现在用的版本
这里Spring6是父工程,它的src文件可有可无,其中的子模块才是重点
第1步 引入spring相关依赖
第2步 创建类,定义属性和方法
第3步 按照spring要求创建配置文件(xml格式)
第4步 在spring配置文件配置相关信息
第5步 进行最终测试
在Maven或Gradle项目中,通过pom.xml或build.gradle文件添加Spring框架及其相关的依赖项,例如Spring Core、Spring Context、Spring DAO等,以便在项目中使用Spring的功能。
在子模块下的Spring-First的pom.xml文件配置以下依赖
- <!-- 依赖关系定义 -->
- <dependencies>
- <!-- 引入Spring Context依赖,它是Spring框架的基础模块,提供了环境配置、Bean生命周期管理、事件传播等功能 -->
- <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>
刷新后并查看依赖
applicationContext.xml
或spring-config.xml
,用于配置Spring容器如何管理和装配bean。在resources文件夹创建Spring配置文件,名字无所谓,但后缀要为 . xml
我这里为 bean.xml
<bean>
标签定义它们的生命周期和依赖关系,也可以配置AOP、事务管理等相关设置。创建完bean.xml配置文件后,配置该文件,像下面这样
- <?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">
-
- <!-- 定义一个Bean实例,id为"helloWorld",类型为com.sakurapaid.spring6_01.HelloWorld类 -->
- <bean id="helloWorld" class="com.sakurapaid.spring6_01.HelloWorld">
-
- </bean>
-
- </beans>
进一步说明:
Bean:在Spring框架中,Bean是一个由Spring IoC(控制反转)容器管理的对象。它是由Spring容器负责创建、装配以及管理其完整生命周期的Java对象。
id属性:每个Bean都需要一个唯一的标识符,id就是用来满足这一需求的属性。通过这个唯一的ID,开发者可以在Spring容器中方便地查找和获取所需的Bean。
class属性:class属性指定用来创建Bean实例的Java类的全限定名。当Spring容器读取到这个配置时,它会根据提供的类名创建对应的类实例,并依据需要进行依赖注入和其他配置处理,最终生成一个可操作的Bean对象供应用程序使用。
创建一个测试类HelloWorldTest,并写上对应内容
- package com.sakurapaid.spring6;
-
- import org.junit.jupiter.api.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class HelloWorldTest {
- @Test
- public void test() {
- //加载spring配置文件,对象创建
- ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
-
- //获取创建对象
- HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
-
- //调用方法,输出结果
- helloWorld.sayHello();
- }
- }
1. 底层是怎么创建对象的,是通过反射机制调用无参数构造方法吗?
修改HelloWorld类:
- public class HelloWorld {
- //无参构造
- public HelloWorld() {
- System.out.println("这是无参构造输出的HelloWorld");
- }
- public void sayHello(){
- System.out.println("HelloWorld");
- }
- }
执行结果:
测试得知:创建对象时确实调用了无参数构造方法。
- // dom4j解析beans.xml文件,从中获取class属性值,类的全类名
- // 通过反射机制调用无参数构造方法创建对象
- Class clazz = Class.forName("com.sakurapaid.spring6.HelloWorld");
- //Object obj = clazz.newInstance();
- Object object = clazz.getDeclaredConstructor().newInstance();
当Spring框架读取配置文件(如beans.xml
)时,它会通过DOM4J等XML解析工具解析出各个bean的定义信息,其中包括bean的类名。之后,Spring利用Java反射机制,通过Class.forName()
方法加载指定类的字节码,然后调用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的定义对象。
创建好的对象并不是立即丢弃,而是由Spring IoC(Inversion of Control,控制反转)容器统一管理。在Spring的底层实现中,对象是以Bean的形式存储在一个名为beanDefinitionMap
的ConcurrentHashMap中。这个Map的键是Bean的名字(通常是类名首字母小写,遵循默认命名规则),值是BeanDefinition对象。BeanDefinition是一个接口,它包含了创建和配置Bean所需的所有元数据信息,如类名、构造函数参数、属性值、依赖关系等。这样,Spring容器就能根据需要随时查找、获取并初始化Bean对象。
HelloWorld
类),Spring会读取这个配置文件,并找到你所指定的类名。Class.forName()
加载指定类的字节码(也就是类的定义)。new
关键字创建对象一样。ConcurrentHashMap
类型),其中:BeanDefinition
对象,它包含了创建和配置Bean所需要的所有细节,比如类的具体位置、属性值、依赖关系等。简单来说,Spring通过读取配置文件,利用反射技术自动创建对象,并把这些对象的相关信息保存在一个特殊的“容器”中。当你需要使用某个对象时,只需告诉Spring它的名称,Spring就会从容器中取出已经创建好的对象给你使用。这样不仅简化了对象的创建过程,也使得对象间的依赖关系更容易管理和维护。这就是Spring框架的核心机制之一——IoC容器的作用。
总结起来就是,Spring通过解析配置文件获取类的信息,运用反射创建对象,并将这些对象以及对象的配置信息以一种高效的数据结构(Map)进行管理,实现了对Bean对象的集中控制和生命周期管理,这就是Spring框架的核心功能之一——IoC容器的运作机制
Apache Log4j2 是一款专为Java应用程序设计的强大且灵活的开源日志框架。在软件开发领域,尤其是在Java项目中,日志扮演着至关重要的角色,它能详尽地记录下系统运行过程中的各种事件和状态变化,就像一本详细的电子日记,涵盖了何时(when)、何地(where)、何种行为(what)以及为何发生(why)等重要信息。
Log4j2 是原始Log4j项目的重大升级版本,相较于传统的System.out.println()方法,它提供了更高级别的功能和控制能力,使得开发者能够根据不同的需求定制日志输出格式、级别、存储位置等,并且支持异步日志处理,提高了系统的性能表现。
以下几个关键特性体现了Log4j2的优势:
总之,Apache Log4j2 提供了一个全面、高效且可高度定制的日志解决方案,有助于提高软件开发效率、简化运维工作,并为系统的稳定性和可靠性提供有力支撑。对于任何Java项目,特别是大型企业级应用来说,选择Log4j2作为日志框架都是一个明智之举。
在pom.xml引入相关依赖
- <!--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>
注意,我这里是写在了父工程里的子工程(Spring6-First)里面的pom文件
在类的根路径下提供log4j2.xml配置文件(文件名固定为:log4j2.xml,文件必须放到类根路径下。)
- <?xml version="1.0" encoding="UTF-8"?>
- <configuration>
- <loggers>
- <!--
- level指定日志级别,从低到高的优先级:
- TRACE < DEBUG < INFO < WARN < ERROR < FATAL
- trace:追踪,是最低的日志级别,相当于追踪程序的执行
- 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="F:/Program/Spring6Log/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="F:/Program/Spring6Log/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>
在resources文件夹右键创建文件——log4j2.xml
注意,log4j2日志运行时会在本地生产日志文件,所以在配置文件里要设置日志文件的存放位置,比如我这里就是F盘下的
F:/Program/Spring6Log/test.log 和 F:/Program/Spring6Log/app.log
根据自己的实际情况来
运行刚才的程序 HelloWorldTest.java得到运行结果
上述为自动写入日志,其实也是可以手动写入日志的,如下述步骤
把刚才的测试类改为这样
- package com.sakurapaid.spring6_01;
-
- import org.junit.jupiter.api.Test;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class HelloWorldTest {
- @Test
- public void test() {
-
- //获取日志对象
- Logger logger = LoggerFactory.getLogger(HelloWorldTest.class);
-
- //加载spring配置文件,对象创建
- ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
-
- //获取创建对象
- HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
-
- //调用方法,输出结果
- helloWorld.sayHello();
-
- //输出日志
- logger.info("### 手动输入日志~");
-
- }
-
- }
测试结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。