Spring 框架核心技术全解析

Spring 框架作为 Java 后端开发的基石,核心围绕控制反转(IOC)面向切面编程(AOP) 两大思想,旨在简化开发、降低模块耦合。本文基于 Spring 5.0.2 版本,从框架介绍、IOC/DI 核心用法、注解开发到 JUnit 整合,全方位拆解 Spring 上半部分核心知识点,附带完整实战代码,适合入门者系统学习。

一、Spring 框架核心认知

1. 什么是 Spring?

Spring 是 2003 年兴起的轻量级 Java EE 一站式框架,由 Rod Johnson 创建。它以 IOC 和 AOP 为核心,解决了业务逻辑层与其他层的耦合问题,支持分层开发(表现层、业务层、持久层),且能无缝集成 MyBatis、Struts2 等主流框架。

2. Spring 的核心优势

  • 解耦简化开发:IOC 容器统一管理对象创建和依赖关系,无需手动 new 对象。
  • AOP 编程支持:轻松实现权限拦截、日志记录等横切逻辑,不侵入业务代码。
  • 声明式事务:通过配置而非硬编码管理事务,降低开发复杂度。
  • 便捷测试:与 JUnit 深度整合,简化测试代码编写。
  • 兼容优秀框架:内置对 MyBatis、Hibernate、Quartz 等框架的支持。
  • 封装复杂 API:简化 JDBC、JavaMail 等难用的 Java EE API。

二、核心技术:IOC 控制反转

1. IOC 核心概念

IOC(Inverse of Control)即控制反转 ,指将对象的创建权从开发者手中 "反转" 给 Spring 框架。开发者无需手动通过new关键字创建对象,而是由 Spring 容器根据配置文件或注解自动实例化对象,彻底解决代码耦合问题。

2. IOC 入门实战(XML 配置方式)

(1)导入依赖(Maven)
XML 复制代码
<dependencies>
    <!-- Spring核心依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!-- 日志依赖 -->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.12</version>
    </dependency>
    <!-- 单元测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>
(2)编写业务接口与实现类
java 复制代码
// 接口
public interface UserService {
    void hello();
}

// 实现类
public class UserServiceImpl implements UserService {
    @Override
    public void hello() {
        System.out.println("Hello IOC!!");
    }
}
(3)编写 Spring 配置文件(applicationContext.xml)

resources目录下创建配置文件,声明 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为Bean名称,class为全类名 -->
    <bean id="userService" class="com.qcbyjy.service.UserServiceImpl" />
</beans>
(4)编写测试类

通过 Spring 容器获取 Bean 并调用方法:

java 复制代码
public class Demo1 {
    @Test
    public void run1() {
        // 加载Spring配置文件,初始化容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 从容器中获取Bean(按id查找)
        UserService userService = (UserService) ac.getBean("userService");
        // 调用方法
        userService.hello(); // 输出:Hello IOC!!
    }
}

3. Bean 的核心配置详解

(1)Bean 的作用范围(scope 属性)
  • singleton:单例(默认值),容器中只创建一个 Bean 实例,全局共享。
  • prototype:多例,每次调用getBean()都会创建新实例。
  • request:Web 环境专用,每次 HTTP 请求创建新 Bean。
  • session:Web 环境专用,同一个 Session 共享一个 Bean。

配置示例:

复制代码
<bean id="userService" class="com.qcbyjy.service.UserServiceImpl" scope="prototype" />
(2)Bean 的生命周期配置
  • init-method:Bean 初始化后执行的方法。
  • destroy-method:Bean 销毁前执行的方法(单例 Bean 随容器关闭销毁,多例 Bean 由垃圾回收销毁)。

配置示例:

java 复制代码
// 实现类中添加初始化和销毁方法
public class UserServiceImpl implements UserService {
    public void init() {
        System.out.println("Bean初始化...");
    }
    public void destroy() {
        System.out.println("Bean销毁...");
    }
    // 业务方法...
}
复制代码
<bean id="userService" class="com.qcbyjy.service.UserServiceImpl" 
      init-method="init" destroy-method="destroy" />
(3)Bean 的三种实例化方式
  • 默认无参构造(推荐):最常用,要求类必须有默认无参构造方法。

    复制代码
    <bean id="userService" class="com.qcbyjy.service.UserServiceImpl" />
  • 静态工厂实例化:通过静态方法创建 Bean。

    java 复制代码
    // 静态工厂类
    public class StaticFactory {
        public static UserService createUserService() {
            return new UserServiceImpl();
        }
    }
    复制代码
    <bean id="userService" class="com.qcbyjy.demo1.StaticFactory" factory-method="createUserService" />
  • 实例工厂实例化:通过工厂实例的非静态方法创建 Bean。

    java 复制代码
    // 实例工厂类
    public class InstanceFactory {
        public UserService createUserService() {
            return new UserServiceImpl();
        }
    }
    复制代码
    <!-- 先配置工厂Bean -->
    <bean id="factory" class="com.qcbyjy.demo1.InstanceFactory" />
    <!-- 通过工厂Bean创建目标Bean -->
    <bean id="userService" factory-bean="factory" factory-method="createUserService" />

三、核心技术:DI 依赖注入

1. DI 核心概念

DI(Dependency Injection)即依赖注入,是 IOC 的具体实现。Spring 容器在创建 Bean 时,会自动将依赖的其他 Bean 或属性值注入到当前 Bean 中,无需开发者手动设置。

2. 依赖注入的三种常用方式

(1)Set 方法注入(最常用)

通过 Bean 的setXxx()方法注入依赖,适用于大多数场景。

示例:注入引用类型(Service 依赖 Dao)+ 基本类型

java 复制代码
// Service实现类
public class OrderServiceImpl implements OrderService {
    // 依赖Dao(引用类型)
    private OrderDao orderDao;
    // 基本类型属性
    private String msg;
    private int age;

    // 必须提供set方法(Spring通过set方法注入)
    public void setOrderDao(OrderDao orderDao) {
        this.orderDao = orderDao;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void saveOrder() {
        System.out.println("业务层:保存订单..." + msg + " - " + age);
        orderDao.saveOrder();
    }
}

// Dao实现类
public class OrderDaoImpl implements OrderDao {
    @Override
    public void saveOrder() {
        System.out.println("持久层:保存订单...");
    }
}

配置文件:

复制代码
<!-- 配置Dao Bean -->
<bean id="orderDao" class="com.qcbyjy.dao.OrderDaoImpl" />

<!-- 配置Service Bean,注入依赖 -->
<bean id="orderService" class="com.qcbyjy.service.OrderServiceImpl">
    <!-- 注入引用类型:ref指向目标Bean的id -->
    <property name="orderDao" ref="orderDao" />
    <!-- 注入基本类型:value直接赋值 -->
    <property name="msg" value="Spring DI" />
    <property name="age" value="20" />
</bean>
(2)构造方法注入

通过 Bean 的带参构造方法注入依赖,适用于依赖必须存在的场景。

示例:

java 复制代码
public class Car {
    private String cname;
    private Double money;

    // 带参构造方法
    public Car(String cname, Double money) {
        this.cname = cname;
        this.money = money;
    }

    @Override
    public String toString() {
        return "Car{" + "cname='" + cname + '\'' + ", money=" + money + '}';
    }
}

配置文件:

xml

复制代码
<bean id="car" class="com.qcbyjy.demo2.Car">
    <constructor-arg name="cname" value="大奔" />
    <constructor-arg name="money" value="400000" />
</bean>
(3)集合类型注入

支持数组、List、Set、Map、Properties 等集合类型的注入。

示例:

java 复制代码
public class CollectionBean {
    private String[] strs; // 数组
    private List<String> list; // List
    private Map<String, String> map; // Map
    private Properties properties; // Properties

    // 提供set方法
    public void setStrs(String[] strs) { this.strs = strs; }
    public void setList(List<String> list) { this.list = list; }
    public void setMap(Map<String, String> map) { this.map = map; }
    public void setProperties(Properties properties) { this.properties = properties; }

    // toString方法...
}

配置文件:

XML 复制代码
<bean id="collectionBean" class="com.qcbyjy.demo3.CollectionBean">
    <!-- 数组注入 -->
    <property name="strs">
        <array>
            <value>张三</value>
            <value>李四</value>
        </array>
    </property>
    <!-- List注入 -->
    <property name="list">
        <list>
            <value>王五</value>
            <value>赵六</value>
        </list>
    </property>
    <!-- Map注入 -->
    <property name="map">
        <map>
            <entry key="user1" value="小明" />
            <entry key="user2" value="小红" />
        </map>
    </property>
    <!-- Properties注入 -->
    <property name="properties">
        <props>
            <prop key="username">root</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
</bean>

四、IOC 注解开发(简化配置)

XML 配置繁琐,Spring 提供注解方式替代 XML,更适合现代开发。

1. 注解开发入门

(1)核心依赖

与 XML 方式一致,无需额外导入依赖。

(2)开启注解扫描

在 XML 配置文件中添加注解扫描,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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解扫描:扫描com.qcbyjy包下所有类 -->
    <context:component-scan base-package="com.qcbyjy" />
</beans>
(3)Bean 注册注解

使用以下注解将类交给 Spring 管理(作用相同,分层标识不同):

  • @Component:通用注解,适用于任意类。
  • @Controller:表现层(Web 层)专用。
  • @Service:业务层专用。
  • @Repository:持久层专用。

示例:

java 复制代码
// 业务层类,指定Bean名称为"userService"
@Service(value = "userService")
public class UserServiceImpl implements UserService {
    @Override
    public void hello() {
        System.out.println("Hello IOC注解...");
    }
}
(4)依赖注入注解
  • @Value:注入基本类型(String、int 等)。
  • @Autowired:默认按类型注入引用类型,需容器中存在唯一对应类型的 Bean。
  • @Qualifier:与@Autowired搭配,按名称注入(解决同类型多个 Bean 的冲突)。
  • @Resource:Java 原生注解,按名称 注入(name属性指定 Bean 名称)。

示例:

java 复制代码
@Component(value = "car")
public class Car {
    // 注入基本类型(无需set方法)
    @Value("大奔")
    private String cname;
    @Value("400000")
    private Double money;

    // 注入引用类型(按类型+名称)
    @Autowired
    @Qualifier(value = "person")
    private Person person;

    // 初始化方法(替代init-method)
    @PostConstruct
    public void init() {
        System.out.println("Car初始化...");
    }

    // toString方法...
}

@Component(value = "person")
public class Person {
    @Value("张三")
    private String pname;

    // toString方法...
}
(5)Bean 作用范围注解
  • @Scope:指定 Bean 作用范围,取值singleton(默认)或prototype

示例:

复制代码
@Service
@Scope(value = "prototype") // 多例
public class UserServiceImpl implements UserService {
    // 业务方法...
}

2. 纯注解开发(无 XML)

纯注解开发是 Spring Boot 的基础,通过配置类替代 XML 文件。

(1)核心注解
  • @Configuration:声明当前类为 Spring 配置类。
  • @ComponentScan:指定注解扫描包(替代<context:component-scan>)。
  • @Import:导入其他配置类(拆分配置时使用)。
  • @Bean:在方法上使用,手动创建 Bean 并交给 Spring 管理(适用于第三方类,如连接池)。
(2)纯注解开发实战
① 编写配置类
java 复制代码
@Configuration // 声明为配置类
@ComponentScan(basePackages = "com.qcbyjy.demo4") // 扫描包
@Import(SpringConfig2.class) // 导入其他配置类
public class SpringConfig {
    // 手动创建第三方Bean(如Druid连接池)
    @Bean(name = "dataSource") // Bean名称为dataSource
    public DataSource createDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }
}

// 其他配置类
@Configuration
public class SpringConfig2 {
    // 可配置其他Bean...
}
② 编写业务类

java

运行

复制代码
@Component
public class Order {
    @Value("北京")
    private String address;

    @Override
    public String toString() {
        return "Order{" + "address='" + address + '\'' + '}';
    }
}
③ 编写测试类
java 复制代码
public class Demo4 {
    @Test
    public void run1() {
        // 加载配置类,初始化容器
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 获取Bean
        Order order = (Order) ac.getBean("order");
        DataSource dataSource = (DataSource) ac.getBean("dataSource");
        System.out.println(order); // 输出:Order{address='北京'}
        System.out.println(dataSource); // 输出Druid连接池对象
    }
}

五、Spring 整合 JUnit 单元测试

传统测试需要手动加载 Spring 容器,整合 JUnit 后可自动注入 Bean,简化测试代码。

1. 导入依

复制代码
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
    <scope>test</scope>
</dependency>

2. 整合方式一:XML 配置

java 复制代码
// 指定JUnit运行器为Spring提供的运行器
@RunWith(SpringJUnit4ClassRunner.class)
// 加载XML配置文件
@ContextConfiguration(locations = "classpath:applicationContext_test.xml")
public class Demo5 {
    // 自动注入Bean
    @Autowired
    private User user;

    @Test
    public void run1() {
        user.sayHello(); // 直接调用方法,无需手动创建容器
    }
}

3. 整合方式二:纯注解配置

java 复制代码
@RunWith(SpringJUnit4ClassRunner.class)
// 加载配置类
@ContextConfiguration(classes = SpringConfig6.class)
public class Demo6 {
    @Autowired
    private Customer customer;

    @Test
    public void run1() {
        customer.save(); // 输出:保存客户...
    }
}

// 配置类
@Configuration
@ComponentScan("com.qcbyjy.demo6")
public class SpringConfig6 {
}

六、总结

Spring 上半部分核心围绕 IOC/DI 展开,关键在于理解 "对象由容器管理,依赖由容器注入" 的思想。开发中可根据场景选择 XML 或注解方式:

  • 小型项目:XML 配置简单直观。
  • 中大型项目 / 微服务:纯注解开发更高效,是 Spring Boot 的基础。

后续将深入学习 Spring AOP、声明式事务等高级特性,掌握这些技术后,能大幅提升开发效率和代码质量。

相关推荐
组合缺一2 小时前
(对标 Spring)OpenSolon v3.7.0, v3.6.4, v3.5.8, v3.4.8 发布(支持 LTS)
java·后端·spring·web·solon
wheeldown2 小时前
【Linux】Linux 地址空间 + 页表映射的概念解析
java·linux·jvm
源码宝2 小时前
一套随访系统源码,医院随访管理系统源码,三级随访平台源码,技术框架:Java+Spring boot,Vue,Ant-Design+MySQL5
java·源码·软件开发·程序·随访·随访系统源码·三级随访
♡喜欢做梦2 小时前
Spring IOC
java·后端·spring
拾忆,想起3 小时前
TCP滑动窗口:网络世界的“智能流量阀门”
java·网络·数据库·网络协议·tcp/ip·php·哈希算法
摇滚侠3 小时前
Spring Boot3零基础教程,Reactive-Stream 发布订阅写法,笔记104 笔记105
java·spring boot·笔记
laplace01235 小时前
Java八股—MySQL
java·mysql·oracle
熙客6 小时前
TiDB:分布式关系型数据库
java·数据库·分布式·tidb
你想考研啊7 小时前
linux安装jdk和tomcat和并自启动
java·linux·tomcat