接下来是对ssm的学习笔记的发布,发布完之后将发布对黑马点评的优化
一、spring
Spring 是一个开源的、轻量级的 Java 企业级应用开发框架,它的核心是 IoC(控制反转) 和 AOP(面向切面编程),旨在简化 Java 开发,尤其是构建大型、复杂、可维护的系统。
Spring 是一个帮你 管理对象、处理依赖、提供基础设施 的“大管家”,让你专注于写业务逻辑,而不是处理底层细节。
1、Spring 的核心功能:
| 功能 | 说明 |
|---|---|
| IoC(控制反转) | 你不再用 new 创建对象,Spring 帮你创建并管理(也叫 DI:依赖注入)。 |
| AOP(面向切面编程) | 把“日志、事务、权限”等横切关注点从业务代码中抽离出来,解耦。 |
| 事务管理 | 不用手动写 beginTransaction()、commit(),Spring 帮你统一管理。 |
| MVC 框架 | Spring MVC 提供了 Web 层开发的支持,替代传统的 Servlet/JSP。 |
| 集成支持 | 轻松整合 MyBatis、JPA、Redis、RabbitMQ、Kafka 等。 |
Spring的MVC架构
| 层级 | 职责一句话 | 核心注解 / 组件 | 开发提示 |
|---|---|---|---|
| 表现层Web / Controller | 接收 HTTP 请求,参数校验,返回响应 | @Controller / @RestController<br>@RequestMapping 系列<br>@RequestBody / @PathVariable<br>@ExceptionHandler<br>HandlerInterceptor | 只写“与协议相关”代码,不写业务 |
| 业务层Service | 核心业务逻辑、事务、规则校验 | @Service<br>@Transactional<br>领域模型 / BusinessException | 事务注解放在这一层;一个 Service 只干一件事 |
| 数据访问层 (持久层)DAO / Repository | 与数据库交互,CRUD | @Repository<br>MyBatis / JPA / Hibernate<br>Entity / Mapper / DataSource | 不出现任何 Web 类;SQL 只在这一层 |
| 基础设施层 Infrastructure | 跨层通用技术能力:配置、缓存、安全、监控、第三方集成 | @Configuration<br>CacheManager<br>Security / 日志 / 消息队列 / 邮件 | 被上层通过 Spring 容器注入,不反向依赖 |

2、Spring 的模块结构(部分)
-
Spring Core:IoC 容器,最核心。
-
Spring AOP:面向切面编程。
-
Spring MVC:Web 开发框架。
-
Spring Boot:快速构建 Spring 应用,约定大于配置。
-
Spring Cloud:微服务架构一站式解决方案。
-
Spring Data:简化数据库访问。
-
Spring Security:安全框架,认证+授权。
3、IoC 和 DI
IoC 和 DI 是 Spring 框架的 核心思想,它们不是新技术,而是一种 设计思想,目的是 解耦。
| 术语 | 全称 | 中文 | 本质 | 一句话理解 |
|---|---|---|---|---|
| IoC | Inversion of Control | 控制反转 | 设计思想 | “你别主动 new 对象,交给容器来管。” |
| DI | Dependency Injection | 依赖注入 | 实现手段 | “容器把依赖‘送’进来,而不是你自己去‘拿’。” |
IoC 是思想,DI 是手段;Spring 通过 DI 实现了 IoC,让你不再 new 对象,专心写业务。
二、容器
1、注册组件
注册 Bean(告诉容器“这个类你要管”)
以下提供部分常见注解
| 注解 | 写在哪儿 | 典型场景 | 备注 |
|---|---|---|---|
| @Bean | 配置类的方法上 | 第三方 jar 里的类、需要复杂构造逻辑的类 | 方法返回值=Bean,方法名=默认 id |
| @Configuration | 类上 | 标记“这个类是配置类”,内部常含 @Bean | 本身也会被 @ComponentScan 扫到 |
| @Component | 自己写的类 | 通用型组件 | 衍生三个子注解:@Service、@Repository、@Controller |
| @ComponentScan | 配置类上 | 指定扫包路径,批量注册 | 不写 value 默认扫当前包及其子包 |
| @Import | 配置类上 | 显式导入另一个配置类 | 用于拆分大型配置 |
| @Conditional... | 与上面任意注解组合 | 按条件注册 | 如 @ConditionalOnClass、 @ConditionalOnProperty |
1.1、@Bean
package org.example.spring01ioc;
import org.example.spring01ioc.bean.Animal;
import org.example.spring01ioc.bean.Person;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import java.util.Map;
@SpringBootApplication
// 启动类的名字和项目的名字一致
public class Spring01IocApplication {
// 所有组件都是单例的,在 ioc 容器启动时就会创建好所有组件对象,每次从容器中获取组件都是从容器中直接获取到组件对象的引用
public static void main(String[] args) {
// 启动 Spring Boot 应用,每次启动都会生成一个新的 ApplicationContext(Spring 应用上下文对象)IOC 容器
// 可使用 ConfigurableApplicationContext 来获取 IOC 容器
ConfigurableApplicationContext ioc = SpringApplication.run(Spring01IocApplication.class, args);
// 容器创建出来即有默认组件,使用 getBean 方法可以获取到一个默认组件,使用 getBeanDefinition 方法可以获取到多个默认组件
Object object = ioc.getBean("spring01IocApplication");
System.out.println("getBean获取单个默认组件:" + object);
String[] beanNames = ioc.getBeanDefinitionNames();
for (String beanName : beanNames) {
System.out.println("name= " + beanName);
}
// 组件名字全局唯一;组件名重复了,一定只会给容器中放一个最先声明的那个。
// 小结:从容器中获取组件
// 1)、组件不存在,抛异常:NoSuchBeanDefinitionException
// 2)、组件不唯一:
// - 按照类型只要一个:否则抛异常:NoUniqueBeanDefinitionException
// - 按照名字只要一个:精确获取到指定对象
// - 多个:返回所有组件的 List 集合
// 3)、组件唯一存在,正确返回。
// 按照组件名字获取一个组件
Person result1 = ioc.getBean("person1", Person.class); // 相当于获取后再强转为 Person 类型
System.out.println("getBean 获取 person1 组件:" + result1);
// 按照组件类型获取一个组件
// Animal result2 = ioc.getBean(Animal.class); // 当容器中只有一个组件时可以直接按照组件类型获取组件
// System.out.println("getBean 获取 animal2 组件:" + result2);
// 按照组件类型获取该类型所有组件
Map<String, Person> result3 = ioc.getBeansOfType(Person.class); // 当容器中只有一个组件时可以直接按照组件类型获取组件
System.out.println("getBean 获取 person2 组件:" + result3);
// 按照组件类型+组件名字获取一个组件
Person result4 = ioc.getBean("person2", Person.class); // 当容器中只有一个组件时可以直接按照组件类型获取组件
System.out.println("getBean 获取 person2 组件:" + result4);
}
// 给 ioc 容器创建自己的组件,组件名就是我们创建的方法名或者是我们 @Bean 中指定的组件名
// 1、创建一个名为 person1 的组件,使用 @Bean 注解添加到 ioc 容器中
@Bean
public Person person1() {
Person person = new Person();
person.setName("张三");
person.setAge(18);
person.setGender("男");
return person;
}
// 2、创建一个名为 person2 的组件,使用 @Bean 注解添加到 ioc 容器中
@Bean("person2")
public Person person() {
Person person = new Person();
person.setName("李四");
person.setAge(18);
person.setGender("男");
return person;
}
// 3、创建一个名为 animal1 的组件,使用 @Bean 注解添加到 ioc 容器中
@Bean("animal1")
public Animal animal() {
Animal animal = new Animal();
animal.setName("狗");
animal.setAge(8);
animal.setGender("公");
return animal;
}
}
1.2、@Configuration
当要配置的组件过多时,可使用@Configuration来说明类为配置类,即将原来所有的@Bean组件分类放入对应的配置类中
1.3、@Component及其衍生的三个注解
在Spring框架中,@Component 是一个核心注解,用于自动检测和配置Spring容器中的Bean。它是Spring组件扫描的基础,任何被 @Component 标注的类都会被Spring识别为一个Bean,并注册到应用上下文中。
| 注解 | 说明 | 使用场景 |
|---|---|---|
@Component | 通用型组件注解 | 任何Spring管理的组件 |
@Controller | 用于表现层(Spring MVC) | 标注控制层组件(如Spring MVC的控制器) |
@Service | 用于业务逻辑层 | 标注服务层组件 |
@Repository | 用于持久层 | 标注DAO层组件(数据库访问层) |
简单来说,该类注解是给我们程序员自己看的,方便我们管理并识别代码用途,分别对应 Spring 中的 MVC 架构
即完全可以使用 @Component 代替所有其他衍生出来的三个注解,本质上都是Spring的Bean。
虽然 @Component 可以替代 @Controller、@Service、@Repository,但使用衍生注解有以下好处:
| 优点 | 说明 |
|---|---|
| 语义清晰 | 明确区分层次结构,代码更易读 |
| 功能增强 | 比如 @Repository 还能自动转换持久层异常为Spring的 DataAccessException |
| AOP支持 | 不同层可以应用不同的切面逻辑(如事务、日志、安全等) |


1.4、@ComponentScan
默认我们的分层注解 (@Component及其衍生的三个注解) 要想生效的前提,我们的组件必须在主程序所在包及其子包结构下,否则无法将其注入我们的 ioc容器,为了解决这个问题,提出@ComponentScan,可自定义你要扫描的包的范围,不过不建议使用,建议老实将组件放在主程序所在包及其子包结构下,条理清晰,可读性好
1.5、@Import
在Java中,@Import注解主要用于Spring框架中,用于导入配置类或组件类。只要在整个项目中导入过一次即可,因为组件是单实例的,建议在config包下单独定义一个类用于使用类似注解
@Configuration
@Import(OtherConfig.class)
public class AppConfig {
// ...
}
1.6、其他注解
①、@Scope
@Scope 是 Spring 框架专门用来“定制 Bean 的生命周期与可见范围”的注解(XML 里也有 <bean scope="..."> 等价写法)。默认情况下,Spring 容器中所有 Bean 都是单例(singleton),即容器启动时创建一次,之后人人共享。通过 @Scope 可以把某个 Bean 改成“每次新建”、“每个 Web 请求一个”、“每个会话一个”等策略。
Ⅰ、基本语法
@Component
@Scope("prototype") // 重点在这行
public class ShopCart {
// 每次注入都拿到全新对象
}
// 或是 Java 的配置类
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public ShopCart shopCart() {
return new ShopCart();
}
}
Ⅱ、范围
| 取值 | 含义 | 适用场景 |
|---|---|---|
singleton | 默认:容器里只存在一份,线程间共享 | 无状态 Service、DAO、工具类 |
prototype | 每次 getBean() / 注入都新建实例 | 有状态、非线程安全对象 |
request | 每个 HTTP 请求一个实例(Web 环境) | 同一次请求内共享数据 |
session | 每个 HTTP Session 一个实例 | 用户级数据,如登录购物车 |
application | 整个 ServletContext 生命周期一个实例 | 全局应用数据,极少用 |
websocket | 每个 WebSocket 连接一个实例 | STOMP 全双工通信 |
其中常见的是 singleton 和 prototype
-
singleton 创建的是单实例的组件对象,容器启动时会创建单实例对象,容器启动完成前创建完成,且容器中只存在一份
-
prototype 创建的是非单实例的组件对象,容器启动时不会创建非单实例对象,什么时候获取什么时候创建
②、@Lazy
@Lazy 是 Spring 的“懒加载”开关:默认单例 Bean 在容器启动时就被实例化;加上 @Lazy 后,第一次真正用到时才创建(延迟初始化)。
@Lazy 在单例模式下可实现组件什么时候获取什么时候创建,而不是在容器启动完成前创建完成,所以可配合 @Scope(singleton)实现懒加载,
Ⅰ、基本语法
@Component
@Lazy // 延迟初始化
public class HeavyService {
public HeavyService() {
System.out.println("HeavyService 实例化 —— 很耗时!");
}
}
// 或是 Java 的配置类
@Configuration
public class AppConfig {
@Bean
@Lazy
public HeavyService heavyService() {
return new HeavyService();
}
}
Ⅱ、控制范围
-
只加在 Bean 定义上:仅对该 Bean 生效
-
加在配置类上:整个配置类里所有
@Bean都变懒@Configuration @Lazy public class AppConfig { @Bean public BeanA a(){ return new BeanA(); } @Bean public BeanB b(){ return new BeanB(); } // 全部懒加载 } -
加在 @ComponentScan:扫描到的组件统一懒加载
@SpringBootApplication @Lazy // 整个项目单例都懒加载(慎用) public class App { }
③、@FactoryBean
FactoryBean是Spring框架中的一个重要接口,它提供了一种更灵活的方式来创建和管理Bean实例。当需要复杂对象的创建逻辑或需要隐藏某些创建细节时,FactoryBean非常有用。
实现它后,Spring 容器会先实例化你的工厂对象,然后调用工厂方法得到真正的业务 Bean,最终把工厂产出的实例注册进容器。
即并非将FactoryBean 注入容器,而是其生产的实例注入容器
Ⅰ、接口中的方法
FactoryBean是一个接口,其中定义了三个方法
public interface FactoryBean<T> {
T getObject() throws Exception; // 返回由FactoryBean创建的实例,即生产真正的 Bean
Class<?> getObjectType(); // 返回创建对象 Bean 的类型
boolean isSingleton(); // 指示是否是单例,默认 true,即返回的是单例的
}
Ⅱ、举例
基本实现示例
public class ConnectionFactoryBean implements FactoryBean<Connection> {
private String url = "jdbc:mysql://localhost:3306/demo";
@Override
public Connection getObject() throws Exception {
return DriverManager.getConnection(url, "root", "root");
// 返回实例,即真正的 Bean 是
}
@Override
public Class<?> getObjectType() {
return Connection.class;
// 返回的是 Connection 的类型
}
@Override
public boolean isSingleton() {
return false;
// 每次都要新连接,即最终返回的不是单例的,是多实例的,什么时候获取什么时候创建
}
}
在Spring配置中注册
@Configuration
public class AppConfig {
@Bean
public ConnectionFactoryBean connectionFactoryBean() {
return new ConnectionFactoryBean(); // 先造工厂
}
}
使用端在应用中可以通过以下方式获取FactoryBean创建的Bean
@Autowired
// 直接注入目标对象
private Connection conn; // 这里注入的是工厂产出的 Connection,而非工厂本身!
最终我们是通过接口中三个方法的 getObject 方法获取对象
④、@Conditonal
@Conditional是Spring 4.0引入的核心注解,它允许条件化地注册Bean,即只有满足特定条件时,相关的Bean定义才会被注册到Spring容器中。
Ⅰ、基本用法
@Configuration
public class AppConfig {
@Bean
@Conditional(MyCondition.class)
public MyService myService() {
return new MyServiceImpl();
}
}
其中MyCondition需要实现Condition接口:
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 在这里实现条件判断逻辑
return true; // 返回true则创建Bean,false则不创建
}
}
Ⅱ、Spring Boot提供的条件注解
-
@ConditionalOnClass: 当类路径存在指定类时生效 -
@ConditionalOnMissingClass: 当类路径不存在指定类时生效 -
@ConditionalOnBean: 当容器中存在指定Bean时生效 -
@ConditionalOnMissingBean: 当容器中不存在指定Bean时生效 -
@ConditionalOnProperty: 根据配置属性决定是否生效 -
@ConditionalOnResource: 当指定资源存在时生效 -
@ConditionalOnWebApplication: 当是Web应用时生效 -
@ConditionalOnNotWebApplication: 当不是Web应用时生效 -
@ConditionalOnExpression: 基于SpEL表达式
当然除了spring boot创建的条件注解,我们也可以自定义条件注解
Spring核心注解详解

864

被折叠的 条评论
为什么被折叠?



