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

【Spring】详细剖析Spring程序

文章目录

  • 一、Spring概述
    • 1. Spring简介
      • 1.1 OCP开闭原则
      • 1.2 依赖倒置原则DIP
      • 1.3 控制反转IoC
    • 2. Spring8大模块
  • 二、Spring的入门程序
    • 1. Spring官网
    • 2. 第一个Spring程序
      • 2.1 创建工程
      • 2.2 配置 pom.xml:
      • 2.3 定义bean:User . java
      • 2.4 配置文件 spring.xml
      • 2.5 编写测试程序
    • 3. 第一个Spring程序详细剖析
      • 3.1 底层创建对象原理
      • 3.2 Spring创建对象的原理
      • 3.3 对象的存储结构
      • 3.4 可有多个spring配置文件
      • 3.5 spring配置文件中的bean可以任意类
      • 3.6 getBean()方法调用
      • 3.7 ClassPathXmlApplicationContext
      • 3.8 超级父接口BeanFactory。
    • 4. Spring6启用Log4j2日志框架

一、Spring概述

1. Spring简介

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。让程序员只需关注核心业务的实现,尽可能的不再关注非业务逻辑代码(事务控制,安全日志等)。

Spring有三个重要特点:

  1. OCP开闭原则
  2. 依赖倒置原则DIP
  3. 控制反转IoC

1.1 OCP开闭原则

在软件开发过程中应当对扩展开放,对修改关闭
如果在进行功能扩展的时候,添加额外的类是没问题的,但因为功能扩展而修改之前运行正常的程序,这是忌讳的。因为一旦修改之前运行正常的程序,就会导致项目整体要进行全方位的重新测试。
这主要是因为:代码和代码之间的耦合度太高,如图所示:
在这里插入图片描述

可以看出,上层是依赖下层的,导致下面只要改动,上面必然会跟着改,这样就同时违背了另一个开发原则:依赖倒置原则

1.2 依赖倒置原则DIP

主要倡导面向接口编程,不要面向具体编程,让上层不再依赖下层,下面改动了,上面的代码不会受到牵连。这样可以大大降低程序的耦合度增强扩展力,同时增强代码复用性
例如:
在这里插入图片描述

虽然已经面向接口编程了,但 new UserDaoImplForOracle() 并没有完全面向接口编程,还是使用到了具体的接口实现类。
如果想要完全面向接口编程(完全符合依赖倒置原则),可以这样编写代码:
在这里插入图片描述

在Spring框架中,它可以帮助我们new对象,并且它还可以将new出来的对象赋到属性上。比如:
在这里插入图片描述

很显然,这种方式是将对象的创建权/管理权交出去了,不再使用硬编码的方式了。同时也把对象关系的管理权交出去了,也不再使用硬编码的方式了。像这种把对象的创建权交出去,把对象关系的管理权交出去,被称为控制反转。

1.3 控制反转IoC

(1)概念:
是面向对象编程中的一种设计思想,可以用来降低代码之间的耦合度,符合依赖倒置原则。
(2)核心:
将对象的创建权交出去,将对象和对象之间关系的管理权交出去,由第三方容器来负责创建与维护。
(3)实现方式:
依赖注入(DI)包括两种方式:

  • set方法注入
  • 构造方法注入

而Spring框架就是一个实现了IoC思想的框架
IoC可以认为是一种全新的设计模式,但是理论和时间成熟相对较晚,并没有包含在GoF中。(GoF指的是23种设计模式)

2. Spring8大模块

在这里插入图片描述

二、Spring的入门程序

1. Spring官网

官网地址:https://spring.io/
官网地址(中文):https://spring.p2hp.com/

2. 第一个Spring程序

2.1 创建工程

(1)打开IDEA创建Empty Project:spring6
(2)设置JDK版本17,编译器版本17【Spring6要求JDK最低版本是Java17
在这里插入图片描述

(3)设置IDEA的Maven:关联自己的maven
在这里插入图片描述

(4)在空的工程spring6中创建模块:spring6-002-first
在这里插入图片描述

2.2 配置 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.lm</groupId>
    <artifactId>spring6-002-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>
  
    <dependencies>
      
        <!-- spring context依赖,表示引入了spring的基础依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
      
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
      
    </dependencies>
  
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

2.3 定义bean:User . java

package com.lm.spring6.bean;

//封装用户信息。
public class User {
}

2.4 配置文件 spring.xml

【该文件放在类的根路径下】
在这里插入图片描述

进行bean的配置,spring才可以帮助我们管理这个对象。

<?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.lm.spring6.bean.User"/>
</beans>
<!--
    Spring配置文件
    IDEA工具提供了这个文件的模板,一定要用这个模板来创建
    文件名随意,最好是放在类路径当中,方便后期移植
-->

bean的id和class属性:

  • id属性:代表对象的唯一标识,不能重名
  • class属性:用来指定要创建的java对象的类名,这个类名必须是全限定类名(带包名)

2.5 编写测试程序

package com.lm.spring6.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FirstSpringTest {
    @Test
    public void testFirstSpringCode() {
        //ApplicationContext是一个接口,有很多实现类
        //ClassPathXmlApplicationContext专门从类路径当中加载spring配置文件的一个spring上下文对象
        //启动spring容器,解析spring.xml文件,实例化所有的bean对象,放在spring容器当中
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        // 根据bean的id从spring容器获取bean对象
        Object userBean = applicationContext.getBean("userBean");
        System.out.println(userBean);
    }
}

运行测试程序
在这里插入图片描述

3. 第一个Spring程序详细剖析

3.1 底层创建对象原理

spring是通过调用类的无参数构造方法来创建对象的

package com.powernode.spring6.bean;

//封装用户信息
public class User {
    public User() {
        System.out.println("User的无参数构造方法执行");
    }
}

运行测试程序:
在这里插入图片描述

如果提供有参数构造方法,不提供无参数构造方法会出现异常。例如:

package com.lm.spring6.bean;

//封装用户的信息
public class User {

//    public User() {
//        System.out.println("User的无参数构造方法执行");
//    }
        public User(String s) {
            System.out.println("User的有参数构造方法执行");
        }
}

运行测试程序:
在这里插入图片描述

3.2 Spring创建对象的原理

// dom4j解析beans.xml文件,从中获取class的全限定类名
// 通过反射机制调用无参数构造方法创建对象
Class clazz = Class.forName("com.powernode.spring6.bean.User");
Object obj = clazz.newInstance();

3.3 对象的存储结构

在这里插入图片描述

3.4 可有多个spring配置文件

从源码中可以看出:
spring的配置文件可以有多个,在ClassPathXmlApplicationContext构造方法的参数上传递文件路径即可。
在这里插入图片描述

3.5 spring配置文件中的bean可以任意类

只要这个类不是抽象的,并且提供了无参数构造方法,在spring配置文件中配置的bean可以任意类
例如: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.lm.spring6.bean.User"/>

    <bean id="userDaoBean" class="com.lm.spring6.dao.UserDaoImplForMySQL"/>

    <bean id="nowtime" class="java.util.Date"/>

</beans>
package com.lm.spring6.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FirstSpringTest {
    @Test
    public void testFirstSpringCode() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml", "beans.xml");
        // 根据bean的id从spring容器获取bean对象
        Object nowtime = applicationContext.getBean("nowtime");
        System.out.println(nowtime);

    }
}

运行测试程序:
在这里插入图片描述

3.6 getBean()方法调用

(1)如果指定的id不存在时,会出现异常

//Object nowtime = applicationContext.getBean("nowtime");
Object nowtime = applicationContext.getBean("nowtime2");
System.out.println(nowtime);

运行测试程序:
在这里插入图片描述

(2)getBean()方法返回的类型是Object,如果访问子类的特有属性和方法时,还需要向下转型

User user = applicationContext.getBean("userBean", User.class);

3.7 ClassPathXmlApplicationContext

ClassPathXmlApplicationContext是从类路径中加载配置文件,如果没有在类路径当中,需要使用FileSystemXmlApplicationContext类进行加载配置文件。
在这里插入图片描述

<?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="vipBean2" class="com.powernode.spring6.bean.Vip"/>
</beans>
ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("d:/spring6.xml");
Vip vip = applicationContext2.getBean("vipBean2", Vip.class);
System.out.println(vip);

这种方式较少用。一般都是将配置文件放到类路径当中,这样可移植性更强

3.8 超级父接口BeanFactory。

BeanFactory是Spring容器的超级接口,ApplicationContext是BeanFactory的子接口。

BeanFactory applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean("userBean", User.class);
System.out.println(user);

测试程序:

@Test
    public void testBeginInitBean() {
        //不是在调用getBean()方法的时候创建对象,执行以下代码的时候就会实例化对象
        new ClassPathXmlApplicationContext("spring.xml");
    }

在这里插入图片描述

4. Spring6启用Log4j2日志框架

从Spring5之后,Spring框架支持集成的日志框架是Log4j2。
(1)引入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="INFO">
            <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)使用日志框架

@Test
    public void testBeginInitBean() {
        //不是在调用getBean()方法的时候创建对象,执行以下代码的时候就会实例化对象
        new ClassPathXmlApplicationContext("spring.xml");

        //创建日志记录器对象,获取FirstSpringTest类的日志记录器对象
        //只要是FirstSpringTest类中的代码执行记录日志的话,就输出相关的日志信息
        Logger logger = LoggerFactory.getLogger(FirstSpringTest.class);
        //根据不同的级别输出日志
        logger.info("我是一条日志消息");
        logger.debug("我是一条调试消息");
        logger.error("我是一条错误消息");

    }

在这里插入图片描述


http://www.kler.cn/a/585937.html

相关文章:

  • 【AWS入门】2025 AWS亚马逊云科技账户注册指南
  • 华三防火墙-HA主备模式
  • 数据结构:UNSW新南学COMP9024真题讲解
  • Redis 事务底层实现
  • Windows下安装Git客户端
  • 438.找出字符串中所有字母异位词
  • 在 CentOS 上安装 Oracle 数据库
  • CentOS 7 系统上安装 SQLite
  • 进程管理:前后台切换
  • 基于OpenMV的车牌识别功能开发与优化研究
  • 落雪音乐Pro 8.8.6 | 内置8条音源,无需手动导入,纯净无广告
  • 【后端】【django】Django 自带的用户系统与 RBAC 机制
  • 面向对象Demo02
  • 面试总结:2024前端面试题
  • 【零基础入门unity游戏开发——unity3D篇】3D物理系统之 —— 3D碰撞器Collider
  • 微信小程序面试内容整理-常用组件
  • 12. Pandas :使用pandas读Excel文件的常用方法
  • CV:图像的直方图均衡化
  • ShineBlink学习日志
  • 【微知】plantuml在泳道图中如何将多个泳道框起来分组并且设置颜色?(box “浏览器“ #LightGreen endbox)