🌔 1、准备工作
(1)创建一个空项目 Spring6,为其配置JDK和Maven
(2)创建一个字模块 spring6-001-revelation
(3)创建 dao、service、web 层,进而创建图片中的文件或目录【MVC】

🌔 2、需求分析
package com.powernode.spring6.dao;
/**
* 持久层,负责对数据增删改查
* @author Bonbons
* @version 1.0
*/
public interface UserDao {
/**
* 根据 id 删除用户信息
*/
void deleteById();
}
package com.powernode.spring6.dao.impl;
import com.powernode.spring6.dao.UserDao;
/**
* @author Bonbons
* @version 1.0
*/
public class UserDaoImplForMySQL implements UserDao {
@Override
public void deleteById() {
System.out.println("MySQL数据库正在删除用户信息......");
}
}
package com.powernode.spring6.service;
/**
* @author Bonbons
* @version 1.0
*/
public interface UserService {
/**
* 删除用户信息
*/
void deleteUser();
}
package com.powernode.spring6.service.impl;
import com.powernode.spring6.dao.UserDao;
import com.powernode.spring6.dao.impl.UserDaoImplForMySQL;
import com.powernode.spring6.service.UserService;
/**
* @author Bonbons
* @version 1.0
*/
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImplForMySQL();
@Override
public void deleteUser() {
userDao.deleteById();
}
}
package com.powernode.spring6.web;
import com.powernode.spring6.service.UserService;
import com.powernode.spring6.service.impl.UserServiceImpl;
/**
* 表示层
* @author Bonbons
* @version 1.0
*/
public class UserAction {
// 创建业务层的对象
private UserService userService = new UserServiceImpl(); [违背DIP原则]
// 删除用户信息的请求
public void deleteRequest(){
userService.deleteUser();
}
}
package com.powernode.spring6.client;
import com.powernode.spring6.web.UserAction;
/**
* @author Bonbons
* @version 1.0
*/
public class Test {
public static void main(String[] args) {
UserAction userAction = new UserAction();
userAction.deleteRequest();
}
}
运行测试:: 可以正常的执行业务

🌔 3、问题分析:
(1)这是我们面向MySQL数据库提供的操作,如果我们想扩展功能,对Oracle数据库提供操作怎么办?
我们可以重写个 UserDaoImplForOracle 接口实现类,但是后面要修改一些代码片段以满足需求。
(2)这样做,就导致了我们这个程序违背了 OCP开闭原则、DIP 依赖倒置原则。
(3)那么什么是 OCP 原则、什么是 DIP 原则呢?
📖 什么是 OCP ?
📖 如何判断是否满足 OCP 原则?
在扩展系统功能时,没有修改原来已经写好的代码,就是符合OCP原则的;反之,就违背了OCP原则
📖 什么是 DIP?

📖 如何判断是否满足依赖倒置原则?
上层不依赖具体的下层,就符合DIP原则,否则就违背了DIP原则
📖 那么对于上述出现的问题我们应该如何解决呢?
我们可以采用控制反转的思想, Inversion of Control
📖 什么是控制反转?反转的是什么?
控制反转是一种编程思想,也有人称之为一种新型的设计模式
反转包括两部分:
引出我们的 Spring 框架
📖 Spring 框架与控制反转有什么关系?
📖 Spring 框架是如何实现控制反转的呢?
📖 1、什么是 Spring ?
📖 2、Spring 的八大模块【在Spring5之后新增了WebFlux模块,之前是七大模块】

(1)Spring Core 模块
(2)Spring Context 模块
(3)Spring AOP 模块
(4)Spring DAO 模块
(5)Spring ORM 模块
(6)Spring Web MVC 模块
(7)Spring WebFlux 模块
Spring Framework 中包含的原始 Web 框架 Spring Web MVC 是专门为 Servlet API 和 Servlet 容器构建的。反应式堆栈 Web 框架 Spring WebFlux 是在 5.0 版的后期添加的。它是完全非阻塞的,支持反应式流(Reactive Stream)背压,并在Netty,Undertow和Servlet 3.1+容器等服务器上运行。
(8)Spring Web 模块
📖 3、Spring 具有哪些特点呢?
📖 4、该系列软件版本的要求:【我以我使用的版本为例】
📖 1、Spring 压缩包解压后的几个文件都代表什么?【因为我用Maven构建项目,所以就不去下载Spring了】
📖 2、对其中一些JRE文件的含义进行解释:
| 包名 | 含义 |
|---|---|
| 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-core-5.3.9.jar | Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。 |
| spring-jdbc-5.3.9.jar | Spring对JDBC的支持。 |
| spring-orm-5.3.9.jar | Spring集成ORM框架的支持,比如集成hibernate,mybatis等。 |
| 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框架的类库 |
📖 3、创建我们的第一个Spring程序
(1)创建一个新的模块: spring6-002-first【普通Maven模块】
(2)修改我们的pom.xml文件,打jar包,导入我们需要的依赖
<!--配置多个仓库repositories标签-->
<repositories>
<repository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<!--配置相关依赖-->
<dependencies>
<!--spring context依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.0-M2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!--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>
</dependencies>
(3)在com.powernode.spring6.bean包下创建User类
package com.powernode.spring6.bean;
/**
* @author Bonbons
* @version 1.0
*/
public class User {
}
在com.powernode.spring6.dao包下创建UserDaoImplForMySQL类
package com.powernode.spring6.dao;
/**
* @author Bonbons
* @version 1.0
*/
public class UserDaoImplFroMySQL {
public void insert(){
System.out.println("MySQL 正在保存用户信息");
}
}
在类的根路径下编写我们的spring.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">
<!--配置信息 id代表唯一标识,class代表全限定类名-->
<bean id="userBean" class="com.powernode.spring6.bean.User" />
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDaoImplFroMySQL" />
</beans>
在com.powernode.spring6.test包下创建FirstSpringTest类
package com.powernode.spring6.test;
import com.powernode.spring6.dao.UserDaoImplFroMySQL;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Bonbons
* @version 1.0
*/
public class FirstSpringTest {
@Test
public void testFirstSpringCode(){
// 获取Spring容器的实例[启动服务]
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
// 根据id获取我们的容器中的具体对象
Object userBean = applicationContext.getBean("userBean");
System.out.println(userBean);
// 获取对象的时候直接指定类型
UserDaoImplFroMySQL userDaoBean = applicationContext.getBean("userDaoBean", UserDaoImplFroMySQL.class);
userDaoBean.insert();
System.out.println(userDaoBean);
}
}

📖 4、根据我们的第一个入门程序分析使用Spring的小技巧:
(1)在Spring配置文件中,通过bean标签加载一个类,id 是其唯一标识,不能重复,class的值为全限定类名
<!--配置了bean,Spring才会替我们管理这个对象-->
<bean id="userBean" class="com.powernode.spring6.bean.User" />
(2)Spring是如何根据类名创建对象的呢?
Class clazz = Class.forName("com.powernode.spring6.bean.User");
Object obj = clazz.newInstance();
return obj;
(3)底层是如何存储为我们创建的对象的呢?
(4)对于我们的spring配置文件有什么要求吗?
(5)我们是通过 getBean(id) 来获取我们的对象的,有什么需要注意的地方吗?
UserDaoImplFroMySQL userDaoBean = applicationContext.getBean("userDaoBean", UserDaoImplFroMySQL.class);
userDaoBean.insert();
System.out.println(userDaoBean);
(6)ApplicationContext 的超级父接口 BeanFactory
// 向下转型
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
Object vipBean = beanFactory.getBean("vipBean");
System.out.println(vipBean);
📖 5、如何启用Spring6集成的Log4j2日志框架呢?
(1)在 pom.xml 文件中引入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>
(2)在类根路径下创建log4j2.xml文件 【文件名和位置是固定的】
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<loggers>
<!--
level指定日志级别,从低到高的优先级:
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
-->
<root level="DEBUG">
<appender-ref ref="spring6log"/>
</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>
</appenders>
</configuration>
(3)之后在运行程序的时候就可以看到日志信息了
(4)如果我们想生成自定义的日志应该怎么办呢?
Logger logger = LoggerFactory.getLogger(FirstSpringTest.class);
logger.info("我是一条日志消息");