1. Spring的下载
官网地址: spring.io/
进入后的路径为:
Artifacts->libs-milestone->org->springframework->spring
下载相应的版本即可
因为目前官方网站下载需要登录JFrog账号,所以我这里选择了国内镜像下载
developer.aliyun.com/mvn/search 国内镜像需要什么的jar包直接下载即可
| JAR文件 | 描述 |
|---|---|
| spring-aop-5.3.9.jar | 这个jar 文件包含在应用中使用Spring 的AOP 特性时所需的类 |
| spring-aspects-5.3.9.jar | 提供对AspectJ的支持,以便可以方便的将面向切面的功能集成进IDE中 |
| spring-beans-5.3.9.jar | 这个jar 文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean 以及进行Inversion ofControl / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI 支持,引入spring-core.jar 及spring-beans.jar 文件就可以了。 |
| spring-context-5.3.9.jar | 这个jar 文件为Spring 核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类。 |
| spring-context-indexer-5.3.9.jar | 虽然类路径扫描非常快,但是Spring内部存在大量的类,添加此依赖,可以通过在编译时创建候选对象的静态列表来提高大型应用程序的启动性能。 |
| spring-context-support-5.3.9.jar | 用来提供Spring上下文的一些扩展模块,例如实现邮件服务、视图解析、缓存、定时任务调度等 |
| spring-core-5.3.9.jar | Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。 |
| spring-expression-5.3.9.jar | Spring表达式语言。 |
| spring-instrument-5.3.9.jar | Spring3.0对服务器的代理接口。 |
| spring-jcl-5.3.9.jar | Spring的日志模块。JCL,全称为"Jakarta Commons Logging",也可称为"Apache Commons Logging"。 |
| spring-jdbc-5.3.9.jar | Spring对JDBC的支持。 |
| spring-jms-5.3.9.jar | 这个jar包提供了对JMS 1.0.2/1.1的支持类。JMS是Java消息服务。属于JavaEE规范之一。 |
| spring-messaging-5.3.9.jar | 为集成messaging api和消息协议提供支持 |
| spring-orm-5.3.9.jar | Spring集成ORM框架的支持,比如集成hibernate,mybatis等。 |
| spring-oxm-5.3.9.jar | 为主流O/X Mapping组件提供了统一层抽象和封装,OXM是Object Xml Mapping。对象和XML之间的相互转换。 |
| spring-r2dbc-5.3.9.jar | Reactive Relational Database Connectivity (关系型数据库的响应式连接) 的缩写。这个jar文件是Spring对r2dbc的支持。 |
| spring-test-5.3.9.jar | 对Junit等测试框架的简单封装。 |
| spring-tx-5.3.9.jar | 为JDBC、Hibernate、JDO、JPA、Beans等提供的一致的声明式和编程式事务管理支持。 |
| spring-web-5.3.9.jar | Spring集成MVC框架的支持,比如集成Struts等。 |
| spring-webflux-5.3.9.jar | WebFlux是 Spring5 添加的新模块,用于 web 的开发,功能和 SpringMVC 类似的,Webflux 使用当前一种比较流程响应式编程出现的框架。 |
| spring-webmvc-5.3.9.jar | SpringMVC框架的类库 |
| spring-websocket-5.3.9.jar | Spring集成WebSocket框架时使用 |
注意:
如果你只是想用Spring的IoC功能,仅需要引入:spring-context即可。将这个jar包添加到classpath当中。
如果采用maven只需要引入context的依赖即可。
2.第一个Spring程序
添加spring context依赖,pom.xml配置如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yantong</groupId>
<artifactId>spring6-001-first</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--spring context依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.0</version>
</dependency>
</dependencies>
</project>
当加入spring context的依赖之后,会关联引入其他依赖:
spring aop:面向切面编程
spring beans:IoC核心
spring core:spring的核心工具包
spring jcl:spring的日志包
spring expression:spring表达式
添加junit依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
定义bean:User
package com.yantong;
/**
* @Author 烔
* @date 2024/10/5
* @Description bean, 封装用户信息
*/
public class User {
}
编写spring的配置文件:beans.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="userBean" class="com.yantong.User"/>
</beans>
bean的id和class属性:
- id属性:代表对象的唯一标识。可以看做一个人的身份证号。
- class属性:用来指定要创建的java对象的类名,这个类名必须是全限定类名(带包名)。
编写测试程序
package com.yantong;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author 烔
* @date 2024/10/5
* @Description 测试类
*/
public class Spring6Test {
/**
* 测试从Spring容器中获取名为"userBean"的Bean
* 该测试方法通过创建一个ClassPathXmlApplicationContext来加载beans.xml配置文件
* 然后从Spring容器中获取名为"userBean"的Bean,并打印该Bean的信息到控制台
*/
@Test
public void testFirst() {
// 创建一个 ClassPathXmlApplicationContext 对象,用于加载 beans.xml 文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
// 从 applicationContext 中获取名为 userBean 的对象
Object userBean = applicationContext.getBean("userBean");
// 打印获取到的 userBean 对象
System.out.println("userBean = " + userBean);
}
}
4. 第一个Spring程序详细剖析
- bean标签的id属性可以重复吗?
在Spring框架中,<bean>标签的id属性是用于唯一标识一个bean的。根据Spring的规范,同一个Spring IoC容器内,<bean>标签的id属性应该是唯一的,不能有重复。如果尝试定义两个具有相同id的bean,Spring容器在启动时会抛出异常,指出存在重复的bean名称。
Vip.java
package com.yantong;
/**
* @Author 烔
* @date 2024/10/5
* @Description
*/
public class Vip {
}
beans.xml
<bean id="userBean" class="com.yantong.Vip"/>
通过测试得出:在Spring配置文件中id是不能重名
- 底层是怎么创建对象的,是通过反射机制调用无参数构造方法吗?
Spring框架在创建对象时确实使用了反射机制,但不仅仅是通过无参数构造方法。Spring提供了多种方式来实例化bean,包括但不限于:
- 默认构造器:如果一个类没有显式地定义任何构造函数,那么Java会自动提供一个无参数的默认构造函数。Spring可以通过这个默认构造函数来实例化bean。这是最简单的情况。
- 带参数的构造器:当一个类有带参数的构造函数,并且这些参数是其他bean或者是由Spring容器管理的值时,Spring可以使用相应的构造函数来实例化bean。这通常发生在需要依赖注入的情况下。
- 静态工厂方法:有时候,可能希望使用静态工厂方法来创建bean。在这种情况下,你可以在配置文件中指定工厂方法的名字,Spring将调用该静态方法来获取bean实例。
- 实例工厂方法:与静态工厂方法类似,但是这里的方法不是静态的,因此你需要首先有一个工厂bean的实例,然后调用其上的非静态方法来创建目标bean。
- FactoryBean接口:实现
FactoryBean接口允许用户自定义复杂的初始化逻辑。当Spring遇到一个标记为FactoryBean类型的bean时,它不会直接返回这个bean本身,而是调用它的getObject()方法来获取实际的对象。 - 特殊作用域和生命周期回调:对于具有特定作用域(如prototype, request, session等)的bean,Spring会在适当的时候创建新的实例。此外,还可以通过实现特定的接口或使用注解来定义初始化后和销毁前的操作。
- 基于注解的配置:使用
@Component,@Service,@Repository,@Controller等注解配合组件扫描功能可以让Spring自动发现并注册bean。 - XML或Java Config配置:无论是通过XML配置文件还是Java配置类,都可以详细指定如何创建bean以及它们之间的关系。
package com.yantong;
/**
* @Author 烔
* @date 2024/10/5
* @Description bean, 封装用户信息
*/
public class User {
public User(){
System.out.println("User的无参数构造方法执行");
}
}
通过测试得知:**创建对象时确实调用了无参数构造方法
如果提供一个有参数构造方法,不提供无参数构造方法会怎样呢?
package com.yantong;
/**
* @Author 烔
* @date 2024/10/5
* @Description bean, 封装用户信息
*/
public class User {
public User(String name){
System.out.println("User的无参数构造方法执行");
}
}
通过测试得知:**Spring是通过调用类的无参数构造方法来创建对象的,所以想让Spring给你创建对象,必须保证无参数构造方法是存在的
Spring 是如何创建对象的呢?原理是什么?
- dom4j解析beans.xml文件,从中获取class的全限定类名
- 通过反射机制调用无参数构造方法创建对象
- 把创建好的对象存储到一个什么样的数据结构当中了呢?
Spring框架将创建好的对象(即bean实例)存储在一个称为BeanFactory的数据结构中,而BeanFactory的最常见实现是ApplicationContext。ApplicationContext不仅提供了BeanFactory的所有功能,还增加了更多的企业级特性,比如AOP、消息资源处理、事件传播等。
在内部,BeanFactory使用一个Map来存储所有的bean实例。这个Map通常是以bean的名字作为键(key),以对应的bean对象作为值(value)。这种设计使得可以通过bean的名字快速地查找和访问到相应的bean实例。
具体来说,DefaultListableBeanFactory类是BeanFactory接口的一个实现,它提供了一个名为beanDefinitionMap的属性,用于存放所有注册过的bean定义信息。当bean被实际创建后,它们会被放入另一个名为singletonObjects的Map中,如果这些bean是单例的话。对于原型(prototype)作用域的bean,则不会存放在singletonObjects中,因为每次请求都会创建一个新的实例。
Map<String,Object>
| key(id) | value(bean) |
|---|---|
| "userBean" | User对象 |
| "vipBean" | Vip对象 |
| "studentBean" | Student对象 |
- spring配置文件的名字必须叫做beans.xml吗?
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
通过以上的java代码可以看出,这个spring配置文件名字是我们负责提供的,显然spring配置文件的名字是随意的。
- 像这样的beans.xml文件可以有多个吗?
spring的配置文件可以有多个,在ClassPathXmlApplicationContext构造方法的参数上传递文件路径即可。这是为什么呢?通过源码可以看到:
- 在配置文件中配置的类必须是自定义的吗,可以使用JDK中的类吗,例如:java.util.Date?
<?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="userBean" class="com.yantong.User"/>
<bean id="vipBean" class="com.yantong.Vip"/>
<bean id="dateBean" class="java.util.Date"/>
</beans>
package com.yantong;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author 烔
* @date 2024/10/5
* @Description 测试类
*/
public class Spring6Test {
/**
* 测试从Spring容器中获取名为"userBean"的Bean
* 该测试方法通过创建一个ClassPathXmlApplicationContext来加载beans.xml配置文件
* 然后从Spring容器中获取名为"userBean"的Bean,并打印该Bean的信息到控制台
*/
@Test
public void testFirst() {
// 创建一个 ClassPathXmlApplicationContext 对象,用于加载 beans.xml 文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
// 从 applicationContext 中获取名为 userBean 的对象
Object userBean = applicationContext.getBean("userBean");
Object dateBean = applicationContext.getBean("dateBean");
// 打印获取到的 userBean 对象
System.out.println("userBean = " + userBean);
System.out.println("dateBean = " + dateBean);
}
}
在spring配置文件中配置的bean可以任意类,只要这个类不是抽象的,并且提供了无参数构造方法。
- getBean()方法调用时,如果指定的id不存在会怎样?
Object hahaha = applicationContext.getBean("hahaha");
当id不存在的时候,会出现异常。
- getBean()方法返回的类型是Object,如果访问子类的特有属性和方法时,还需要向下转型,有其它办法可以解决这个问题吗?
User userBean1 = applicationContext.getBean("userBean", User.class);
- ClassPathXmlApplicationContext是从类路径中加载配置文件,如果没有在类路径当中,又应该如何加载配置文件呢?
ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("d:/spring6.xml");
没有在类路径中的话,需要使用FileSystemXmlApplicationContext类进行加载配置文件。
这种方式较少用。一般都是将配置文件放到类路径当中,这样可移植性更强。
- ApplicationContext的超级父接口BeanFactory。
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
Object vipBean = beanFactory.getBean("vipBean");
System.out.println(vipBean);
BeanFactory是Spring容器的超级接口。ApplicationContext是BeanFactory的子接口。
5. Spring6启用Log4j2日志框架
从Spring5之后,Spring框架支持集成的日志框架是Log4j2.如何启用日志框架:
第一步:引入Log4j2的依赖
<!--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>
第二步:在类的根路径下提供log4j2.xml配置文件(文件名固定为:log4j2.xml,文件必须放到类根路径下。)
Logger logger = LoggerFactory.getLogger(Spring6Test.class);
logger.info("我是一条日志消息");