背景

本文是《Java 后端从小白到大神》修仙系列之框架学习,Java框架之Spring框架第一篇。本篇文章主要聊Java框架,那么必然从Spring框架开始,可以说Spring框架是Java企业级开发的基石,我们现在开始吧。

文章概览

  1. 核心容器(Core Container)

Spring框架

核心容器(Core Container)

graph TD
    A[Spring框架核心] --> B[Core Container<br>IoC容器]
    B --> B1[spring-beans<br>组件定义]
    B --> B2[spring-context<br>运行时环境]
    B --> B3[spring-core<br>基础工具]
    
    B --> C[AOP模块]
    B --> D[数据访问模块]
    B --> E[Web模块]
    
    classDef box fill:#f9f9f9,stroke:#333,stroke-width:1px;
    class A,B,C,D,E box;

图可以看出来 Core Container 是 Spring 的基石,即常说的IoC容器。在此基础上才有AOP,DATA和WEB的繁荣,所有其他的 Spring 组件都是在容器上构建出来的。

  • 包含三大核心模块:

    • spring-beans:定义和装配组件(Bean)
    • spring-context:提供运行时环境(Bean的"舞台")
    • spring-core:提供基础工具(支撑的"道具")
  • Spring 的整个设计哲学

    • Bean 是应用程序中的对象
    • Spring 的整个设计哲学都围绕着组件(Bean)展开,一切皆为了bean
    • 框它们是实际执行业务逻辑的“参与者”或“组件”
  • 分层架构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
┌─────────────────┐
│    Web层        │ ← 构建在容器之上
├─────────────────┤
│   数据访问层     │ ← 构建在容器之上
├─────────────────┤
│     AOP层       │ ← 构建在容器之上
├─────────────────┤
│  Core Container │ ← 核心容器(基石)
│  ┌────────────┐ │
│  │  Context   │ → Bean的"舞台"
│  ├────────────┤ │
│  │   Beans    │ → 业务"演员"
│  ├────────────┤ │
│  │   Core     │ → 基础"道具"
└──┴────────────┴─┘
  • 模块比喻
模块 角色 功能描述
Context 舞台 是 Spring IoC 容器的具体实现,它负责管理 Bean 的生命周期、配置和依赖注入,就像一个为演员提供环境并协调他们表演的“舞台”
Beans 演员 Bean 是应用程序中的对象,它们是实际执行业务逻辑的“参与者”或“组件”
Core 道具 提供了 Spring 框架最基础的、底层的通用工具和实用程序,例如资源管理、类型转换等,这些是支持容器和 Bean 运作的“道具”或“基础设施”

1. Spring 架构图

graph TB
    subgraph "SPRING FRAMEWORK RUNTIME"
        subgraph " "
            direction TB
            subgraph "Data Access/Integration"
                A1[JDBC] --> A2[ORM]
                A3[OXM] --> A4[JMS]
                A5[Transactions]
            end

            subgraph "Web (MVC/Remoting)"
                B1[Web] --> B2[Servlet]
                B3[Portlet] --> B4[Struts]
            end
        end

        subgraph "  "
            direction TB
            subgraph "AOP"
                C1[AOP]
            end

            subgraph "Aspects"
                D1[Aspects]
            end

            subgraph "Instrumentation"
                E1[Instrumentation]
            end

            subgraph "Messaging"
                E2[Messaging]
            end
        end

        subgraph "   "
            subgraph "Core Container"
                F1[Beans] 
                F2[Core]
                F3[Context]
                F4[Expression Language]
            end
        end

        subgraph "Test"
            G1[Test]
        end
        
    end

2. 什么是 Spring 容器

Spring 容器就是一个管理对象(Bean)生命周期和 Bean 之间依赖关系的容器。
简单说,它负责:

  • 创建对象(Bean实例化)
  • 维护对象之间的依赖关系(依赖注入)
  • 管理对象的生命周期(初始化、销毁)
  • 提供容器级的扩展(AOP、事件发布、资源加载等)

从本质上讲,Spring 容器就是一个高级的工厂模式实现,管理了对象的创建、组装、生命周期,同时提供了扩展点。一句话总结:Spring容器 = 一个高级的对象工厂 + 生命周期管理 + 提供扩展

3. Spring 容器的组成

Spring的容器,本质是对 BeanFactoryApplicationContext 两个大接口体系的不断扩展和实现。

(1)BeanFactory 系列(基础容器接口)

BeanFactory 是最底层、最基本的Spring容器接口,负责管理Bean的生命周期,DefaultListableBeanFactory 是大部分情况下真正承载所有Bean定义和实例管理的容器核心。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
BeanFactory (基础工厂)
├── HierarchicalBeanFactory(分层父子容器)
├── ListableBeanFactory(可以列出Bean的名字/类型)
└── AutowireCapableBeanFactory(支持自动注入和Bean生命周期回调)
      └── ConfigurableBeanFactory(可配置BeanFactory,比如添加后置处理器、作用域、值解析器)
             └── DefaultListableBeanFactory(最常用的Bean工厂实现类)

(2)ApplicationContext 系列(高级容器接口)

ApplicationContext 是对 BeanFactory 的功能增强,提供了:

  • 国际化(MessageSource)
  • 资源加载(ResourceLoader)
  • 应用事件发布(ApplicationEventPublisher)
  • 容器环境管理(EnvironmentCapable)

AbstractApplicationContext 定义了容器启动、刷新、关闭的基本流程(如refresh()方法)。GenericApplicationContext 是纯净、轻量的手动控制型容器。AnnotationConfigApplicationContext注解驱动的标准容器,常用于比较新的Spring应用。ClassPathXmlApplicationContextXML配置传统容器。WebApplicationContextWeb应用专用容器,嵌套了Servlet环境的支持。

结构如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
BeanFactory (核心容器接口)
└── ApplicationContext (应用上下文接口)
    │   (扩展自BeanFactory)
    └── (ApplicationContext 额外提供的能力/实现的接口,全部直接继承ApplicationContext)
    │    ├── EnvironmentCapable (管理环境属性)
    │    ├── ResourceLoader (加载资源,如classpath:、file:、url)
    │    ├── ApplicationEventPublisher (事件发布机制)
    │    └── MessageSource (国际化消息源)
    ├── ConfigurableApplicationContext(可配置的ApplicationContext,提供refresh/close)
    │   │ (继承自ApplicationContext)
    │   │
    │   └── AbstractApplicationContext(ApplicationContext抽象基础实现类,实现了容器启动、关闭、刷新流程)
    │       │ (实现ConfigurableApplicationContext接口)
    │       │
    │       ├── GenericApplicationContext(通用容器,可手动注册Bean定义)
    │       │   │ (继承自AbstractApplicationContext)
    │       │   │
    │       │   └── AnnotationConfigApplicationContext(非Web注解容器,标准Java应用使用)
    │       │       (继承自GenericApplicationContext)
    │       │
    │       ├── ClassPathXmlApplicationContext(XML配置容器,传统用法)
    │       │   (继承自AbstractApplicationContext的一个分支)
    │       │
    │       └── (Web容器具体实现类,它们也实现WebApplicationContext接口)
    │           ├── GenericWebApplicationContext(通用Web容器)
    │           │   (继承自GenericApplicationContext,并实现WebApplicationContext接口)
    │           │
    │           ├── AnnotationConfigWebApplicationContext(注解配置Web容器,现代Spring Web应用常用)
    │           │   (继承自AbstractApplicationContext的一个分支,并实现WebApplicationContext接口)
    │           │
    │           └── XmlWebApplicationContext(XML配置Web容器,传统Web应用使用)
    │               (继承自AbstractApplicationContext的一个分支,并实现WebApplicationContext接口)
    ├── WebApplicationContext(用于Web环境的接口)
    │   (继承自ApplicationContext。其具体实现类已在AbstractApplicationContext分支下详细列出)
    │   │
    │   └── 所有Web容器实现类(如GenericWebApplicationContext)
    │   (必须实现WebApplicationContext接口)

(3)特别关键的几个容器实现类

容器实现类 说明
DefaultListableBeanFactory 真正存储和管理所有Bean定义和实例的底层工厂,几乎所有场景都依赖它
AbstractApplicationContext 定义了容器的生命周期(如refresh/close),模板方法模式
GenericApplicationContext 轻量、灵活,可以自己注册BeanDefinition,不绑定具体配置形式
AnnotationConfigApplicationContext 基于注解(@Configuration,@ComponentScan)启动容器,Spring Boot默认使用它
ClassPathXmlApplicationContext 通过加载XML配置文件启动容器(老项目常见)
WebApplicationContext Web环境容器,支持ServletContext,Spring MVC使用它

一句话总结:Spring容器 = 基础的BeanFactory(负责Bean生命周期) + 高级的ApplicationContext(负责环境、事件、国际化)组成。
实际运行时:

  • DefaultListableBeanFactory负责底层数据存储
  • AbstractApplicationContext负责顶层调度流程,常用的有:
    • 注解版(AnnotationConfigApplicationContext)
    • XML版(ClassPathXmlApplicationContext)
    • Web版(WebApplicationContext)

4. refresh() 方法流程详解

Spring 容器的refresh()方法是初始化容器的核心流程,就像工厂的生产线一样,按顺序完成从 “原材料准备” 到 “成品交付” 的全过程。整个流程可分为 13 个关键步骤,核心是:加载配置→解析 Bean 定义→初始化 Bean→完成容器启动。

(1) refresh() 方法核心步骤流程图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
1. refresh()
│   └── 作为入口方法,协调后续所有步骤,比喻:类似工厂的 "启动生产" 按钮。
├── 2. prepareRefresh() 
│   └── 容器准备阶段(初始化环境属性、设置启动时间、校验配置)
│   └── 比喻:像工厂开工前检查水电、原材料库存是否充足
├── 3. obtainFreshBeanFactory()
│   └── 获取新的 BeanFactory(加载配置,创建/刷新BeanFactory,并解析BeanDefinition)
│   └── 真正解析 @Bean、@Component、@Service 注解,产生 BeanDefinition 的地方是在obtainFreshBeanFactory() ➔ refreshBeanFactory() ➔ loadBeanDefinitions()
│   └── 这里是 Bean 定义的 "诞生地",所有 Bean 的元数据(如类名、依赖关系)都会被解析并存储到 BeanFactory 中
├── 4. prepareBeanFactory(beanFactory)
│   └── 配置BeanFactory基本属性(ClassLoader、后置处理器等)
│   └── 比喻:给工厂配备必要的生产设备和基础管理制度。
├── 5. postProcessBeanFactory(beanFactory)
│   └── 是模板方法,继承AbstractApplicationContext子类,重写postProcessBeanFactory()模板方法,在方法中修改 BeanFactory 的基础配置(如注册特殊处理器),属于框架预留的,简单说是修改beanFactory
│   └── 比如定义CustomApplicationContex继承ClassPathXmlApplicationContext,重写postProcessBeanFactory方法,beanFactory.addBeanPostProcessor(new CustomBeanPostProcessor())
│   └── post前缀 表示 后置的、后续阶段,意思是在BeanFactory准备好之后,Bean定义已经加载完毕了,但还没正式创建Bean对象前,给开发者修改bean定义的机会
│   └── 而 BeanFactoryPostProcessor 是接口(由开发者实现),该接口有postProcessBeanFactory()唯一方法,是真正的 "后置处理器",用于修改 BeanDefinition(如修改作用域、添加属性),简单说是修改BeanDefinition
├── 6. invokeBeanFactoryPostProcessors(beanFactory)
│   └── 调用BeanFactoryPostProcessor,比如修改BeanDefinition(超重要)
│   └── PostProcessor后置处理器,在 BeanFactory 初始化后,做一些加工处理,是 “执行处理的对象/角色”
│   └── 比喻:工厂的 "设计师" 进场,根据实际需求修改 Bean 的 "设计图纸"(BeanDefinition)
├── 7. registerBeanPostProcessors(beanFactory)
│   └── 注册BeanPostProcessor,比如AOP、事务等功能的核心
│   └── 比喻:工厂的 "质检人员" 进场,负责在 Bean 生产(初始化)过程中进行质量检测和加工。
├── 8. initMessageSource()
│   └── 国际化消息源初始化
├── 9. initApplicationEventMulticaster()
│   └── 初始化事件发布器(ApplicationEventPublisher)
│   └── 如后续可通过 applicationContext.publishEvent () 发布事件
├── 10. onRefresh()
│   └── 留给子类扩展(比如SpringMVC初始化DispatcherServlet),由具体容器实现(如 WebApplicationContext)重写,用于特殊初始化
├── 11. registerListeners()
│   └── 注册事件监听器,找到所有实现了 ApplicationListener 接口的类
│   └── 注册到事件系统中,用于监听容器事件(如 ContextRefreshedEvent)
├── 12. finishBeanFactoryInitialization(beanFactory)
│   └── 真正实例化非懒加载的单例Bean,应用 BeanPostProcessor 进行加工(如 AOP 代理)
│   └── 比喻:工厂开始按 "设计图纸" 生产 Bean 成品,并进行质检(后置处理器处理)。
└── 13. finishRefresh()
    └── 通知监听器,刷新完成,整个容器可用了,触发生命周期回调(如SmartInitializingSingleton)
    └── 至此,容器正式可用,所有单例 Bean 已准备就绪

(2) refresh() 方法核心步骤流程图

继续从 refresh() 过程中,对特别重要的步骤源码分析,比如:

  • invokeBeanFactoryPostProcessors
  • registerBeanPostProcessors
  • finishBeanFactoryInitialization

invokeBeanFactoryPostProcessors 内部发生了什么?

这个步骤非常非常重要!

主要完成了:

  • 处理所有 BeanDefinitionRegistryPostProcessor(用于动态注册新的Bean)
  • 处理所有 BeanFactoryPostProcessor(用于修改现有Bean定义)

源码(简化版逻辑)大致是:

1
2
3
4
5
6
7
8
9
// Step1:先调用 BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()
for (BeanDefinitionRegistryPostProcessor registryProcessor : registryProcessors) {
    registryProcessor.postProcessBeanDefinitionRegistry(registry);
}

// Step2:再调用所有 BeanFactoryPostProcessor.postProcessBeanFactory()
for (BeanFactoryPostProcessor factoryProcessor : factoryProcessors) {
    factoryProcessor.postProcessBeanFactory(beanFactory);
}

特别提示:Spring Boot的自动配置原理,就是在这个阶段动态注册Bean定义(比如通过@ConditionalOnMissingBean)。MyBatis、Spring Cloud 等框架,也是这里通过扫描/动态添加Bean的。 所以,invokeBeanFactoryPostProcessors动态注册和修改Bean定义的关键步骤!

registerBeanPostProcessors 内部发生了什么?

这是注册BeanPostProcessor的阶段!

BeanPostProcessor是干嘛的?

  • Bean实例化前后 插入自定义逻辑,比如AOP代理、事务增强、@Autowired注入处理等等。

流程是这样的(简化):

1
2
3
4
List<BeanPostProcessor> postProcessors = findBeanPostProcessors();
for (BeanPostProcessor processor : postProcessors) {
    beanFactory.addBeanPostProcessor(processor);
}

特别注意:BeanPostProcessor自己也是个Bean,但要提早实例化,因为后续需要依赖它们处理普通Bean!Spring AOP的代理创建,就是靠BeanPostProcessor(比如 ProxyBeanPostProcessor)在这里注册的。

finishBeanFactoryInitialization 内部发生了什么?

终于开始实例化真正的Bean了!

这里做了两件大事:

  1. 初始化 ConversionServiceembeddedValueResolver 等环境工具
  2. 实例化所有非懒加载单例Bean

最关键的是这句代码:

1
beanFactory.preInstantiateSingletons();

preInstantiateSingletons() 做的事情是:

  • 遍历所有BeanDefinition
  • 对于单例非懒加载的Bean
    • 调用 getBean(beanName)
    • 创建Bean(如果还没实例化)

(3) Bean生命周期时序图

refresh()
│
├── invokeBeanFactoryPostProcessors
│      └── 处理 BeanDefinitionRegistryPostProcessor
│      └── 处理 BeanFactoryPostProcessor
│
├── registerBeanPostProcessors
│      └── 注册 BeanPostProcessor(AOP,事务,@Autowired处理器)
│
├── finishBeanFactoryInitialization
│      └── preInstantiateSingletons()
│          ├── 实例化Bean(调用构造器)
│          ├── populateBean(填充属性,@Autowired)
│          ├── 调用 BeanPostProcessor.postProcessBeforeInitialization()
│          ├── 调用 @PostConstruct、InitializingBean.afterPropertiesSet()
│          ├── 调用 BeanPostProcessor.postProcessAfterInitialization()
│
└── finishRefresh()
       └── 发布 ContextRefreshedEvent
       └── 调用 SmartInitializingSingleton.afterSingletonsInstantiated()

5. 依赖注入与控制反转原理

  • 控制反转(IoC)概念:将对象创建与依赖管理的控制权从应用程序代码中“反转”到容器中。应用不再主动new依赖对象,而是由容器负责组装所需组件。
  • 依赖注入(DI)概念:IoC 的具体实现方式之一,通过将所需依赖(例如 service、repository)注入到目标对象中,减少硬编码耦合。

6. Spring 中如何实现 IoC/DI

Spring 容器(BeanFactory/ApplicationContext)负责:

  • 加载 Bean 定义:读取 XML 配置文件、扫描带注解的类、或解析 @Configuration@Bean 注解。
  • 管理 Bean 生命周期:实例化、依赖注入、初始化回调、销毁回调等流程统一管理。
  • 注入依赖:根据类型(byType)、名称(byName)或构造函数参数,将所需 Bean 自动注入。

7. 三种 Bean 定义方式与原理

(1)XML 配置

  • applicationContext.xml 中以 <bean id="userService" class="com.example.UserService" 标签定义。

  • Spring 使用 JAXP XML 解析器读取元素,将 class 属性映射为对应 Java Class,通过反射实例化并注入属性或构造函数。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    <!-- applicationContext.xml -->
    <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="userRepository" class="com.example.UserRepository"/>
        <bean id="userService" class="com.example.UserService">
            <constructor-arg ref="userRepository"/>
        </bean>
    </beans>
    

(2)Java 注解

  • 通过 @Configuration 类和 @Bean 方法在 Java 代码中直接定义 Bean。

  • Spring 在启动时扫描带 @Configuration 的类,解析 @Bean 方法,使用反射调用并管理方法返回的对象。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    @Configuration
    public class AppConfig {
        @Bean
        public UserRepository userRepository() {
            return new UserRepository();
        }
    
        @Bean
        public UserService userService(UserRepository repo) {
            return new UserService(repo);
        }
    }
    

(3)类路径扫描(Component Scan)

  • 在主配置上使用 @ComponentScan 指定包路径,Spring 扫描带有 @Component@Service@Repository@Controller 等注解的类。

  • Spring 使用 ASM 或反射读取 Class 文件中的注解元数据,将这些类注册为 BeanDefinition,再实例化注入。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    @Configuration
    @ComponentScan("com.example")
    public class AppConfig {}
    
    @Service
    public class UserService {
        @Autowired
        private UserRepository repo;
        // ...
    }
    
    @Repository
    public class UserRepository {
        // ...
    }
    

为什么 Java 能支持这三种方式?

  • 反射机制:Java 提供 Class.forName()ConstructorMethod 等反射 API,Spring 可以动态加载并实例化任意类。
  • 注解处理:Java 注解会在编译时或运行时保留元数据,Spring 能借助 AnnotationMetadata 与 ASM 库读取并处理。
  • 类加载与资源访问:Spring 能通过 ResourceLoader 访问类路径下的 XML、Properties、Class 文件,实现统一配置加载。

8. Bean 生命周期与作用域(Scopes)

8.1 Bean 作用域

  • singleton(单例,默认):整个 Spring IoC 容器中仅创建一个共享 Bean 实例。适合无状态、线程安全的对象。
  • prototype(原型):每次通过容器获取 Bean 时都创建一个新实例;容器不管理销毁生命周期,你需要自行管理 prototype Bean 的销毁。适合有状态对象。
  • request(Web 应用):在一次 HTTP 请求内有效,每次请求都会新建一个 Bean,请求结束后销毁。
  • session(Web 应用):在一个 HTTP 会话内有效,每个会话一个 Bean,Session 过期或失效后销毁。
  • application(Web 应用):与 ServletContext 作用域相同,整个 web 应用生命周期内共享一个 Bean。

示例:声明不同作用域 Bean

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Component
@Scope("prototype")
public class ShoppingCart {
    private List<Item> items = new ArrayList<();
    public void add(Item i) { items.add(i); }
}

@Component
// 单例 在 Spring 容器启动时就会被创建,并且只创建一次。假设单例 SingletonBeanA 被创建时,Spring 会尝试注入它所依赖的 RequestData
// 但是,RequestData 是 request 作用域的。这意味着每次 HTTP 请求都应该有一个新的 RequestData 实例
// 于是 Spring 不会直接注入 RequestData 的实例到 SingletonBeanA 中,而是注入一个 RequestData 的代理对象
// 当 SingletonBeanA 调用代理对象的方法时,代理对象会拦截这个调用,并在每次调用时,从当前作用域(即当前的 HTTP 请求作用域)中查找或创建一个真正的 RequestData 实例,然后将方法调用转发给这个真正的实例
// 若是RequestData Bean 必须实现至少一个接口,则为ScopedProxyMode.INTERFACES,Spring 会为 Bean 创建一个基于JDK 动态代理的代理对象
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestData {
    private String id = UUID.randomUUID().toString();
    public String getId() { return id; }
}

8.2 Bean 生命周期回调

  • 实例化阶段:Spring 通过反射调用无参构造器创建 Bean。
  • 依赖注入阶段:填充属性、调用构造函数注入。
  • Aware 回调:若实现 BeanNameAwareBeanFactoryAware 等接口,Spring 会注入对应容器引用。
  • BeanPostProcessor 前置处理:调用 postProcessBeforeInitialization。常用于实现自定义注解逻辑,在 Bean 的初始化回调 之前,修改/预处理 Bean(如自定义注解处理)。
  • 初始化回调(从高优先级到低优先级):
    • 使用 @PostConstruct 注解标记方法
    • 或实现 InitializingBeanafterPropertiesSet() 方法
    • 或通过 @Bean(initMethod) 指定
  • BeanPostProcessor 后置处理:调用 postProcessAfterInitialization。在 Bean 的初始化回调 之后,为 Bean 创建代理(如 AOP、事务)。
  • 销毁回调(仅 singleton,从高优先级到低优先级):
    • 使用 @PreDestroy 注解
    • 或实现 DisposableBeandestroy() 方法
    • 或通过 @Bean(destroyMethod) 指定

示例:完整生命周期回调

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@Component
public class LifeCycleBean implements InitializingBean, DisposableBean {
    @PostConstruct
    public void postConstruct() { System.out.println("@PostConstruct"); }
    @Override
    public void afterPropertiesSet() { System.out.println("afterPropertiesSet"); }
    @Bean(initMethod="customInit", destroyMethod="customDestroy")
    public void customInit() { System.out.println("custom init"); }
    @PreDestroy
    public void preDestroy() { System.out.println("@PreDestroy"); }
    @Override
    public void destroy() { System.out.println("DisposableBean destroy"); }

    // 尽管 customDestroy() 方法本身没有 @PreDestroy 注解,但它已经被,@Bean(destroyMethod="customDestroy") 明确指定为销毁方法
    public void customDestroy() { System.out.println("custom destroy"); }
}

示例:创建两种上下文并加载 Bean

1
2
3
4
5
6
7
8
// BeanFactory 示例
Resource res = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(res);
MyService svc1 = factory.getBean(MyService.class); // 触发加载

// ApplicationContext 示例
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService svc2 = ctx.getBean(MyService.class); // Bean 已预实例化

9. 手写一个Mini版Spring容器

V1.0版(最小可用) 版本,先实现这几个基本功能:

  • 注册Bean定义(BeanDefinition)
  • 创建Bean实例
  • 通过getBean拿到实例
  • 有一个类似refresh()的方法初始化容器
1. 定义 BeanDefinition 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 保存Bean的元信息,比如class类型
public class BeanDefinition {
    private Class<?> beanClass;

    public BeanDefinition(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    public Class<?> getBeanClass() {
        return beanClass;
    }
}
2. 定义 MiniApplicationContext 容器
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.HashMap;
import java.util.Map;

public class MiniApplicationContext {

    // 保存注册的Bean定义
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    // 保存创建好的单例Bean实例
    private Map<String, Object> singletonBeans = new HashMap<>();

    // 注册Bean定义
    public void registerBeanDefinition(String name, Class<?> beanClass) {
        beanDefinitionMap.put(name, new BeanDefinition(beanClass));
    }

    // 初始化(类似refresh)
    public void refresh() {
        // 遍历bean定义,实例化bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition definition = entry.getValue();
            try {
                Object bean = definition.getBeanClass().getDeclaredConstructor().newInstance();
                singletonBeans.put(beanName, bean);
            } catch (Exception e) {
                throw new RuntimeException("Failed to create bean: " + beanName, e);
            }
        }
    }

    // 获取Bean
    public Object getBean(String name) {
        return singletonBeans.get(name);
    }
}
3. 测试用例:UserService 类
1
2
3
4
5
public class UserService {
    public void sayHello() {
        System.out.println("Hello, Mini Spring!");
    }
}
4. 测试启动
1
2
3
4
5
6
7
8
9
public class TestMiniSpring {
    public static void main(String[] args) {
        MiniApplicationContext context = new MiniApplicationContext();
        context.registerBeanDefinition("userService", UserService.class);
        context.refresh();
        UserService userService = (UserService) context.getBean("userService");
        userService.sayHello(); // 输出: Hello, Mini Spring!
    }
}

V2.0版,在V1的基础上实现依赖注入:

  • 注册 Bean
  • 实例化 Bean
  • refresh 初始化
  • getBean 取出
  • Setter方法自动依赖注入
1. 改进版 MiniApplicationContext
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class MiniApplicationContext {

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private Map<String, Object> singletonBeans = new HashMap<>();

    public void registerBeanDefinition(String name, Class<?> beanClass) {
        beanDefinitionMap.put(name, new BeanDefinition(beanClass));
    }

    public void refresh() {
        // 第一步:实例化所有Bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition definition = entry.getValue();
            try {
                Object bean = definition.getBeanClass().getDeclaredConstructor().newInstance();
                singletonBeans.put(beanName, bean);
            } catch (Exception e) {
                throw new RuntimeException("Failed to create bean: " + beanName, e);
            }
        }

        // 第二步:依赖注入(setter注入)
        for (Map.Entry<String, Object> entry : singletonBeans.entrySet()) {
            Object bean = entry.getValue();
            injectDependencies(bean);
        }
    }

    private void injectDependencies(Object bean) {
        Method[] methods = bean.getClass().getMethods();
        for (Method method : methods) {
            // 找到所有setter方法
            if (isSetter(method)) {
                Class<?> paramType = method.getParameterTypes()[0];
                // 根据类型找到容器中已有的Bean
                Object dependency = findBeanByType(paramType);
                if (dependency != null) {
                    try {
                        method.invoke(bean, dependency);
                    } catch (Exception e) {
                        throw new RuntimeException("Failed to inject dependency: " + method.getName(), e);
                    }
                }
            }
        }
    }

    private boolean isSetter(Method method) {
        return method.getName().startsWith("set")
                && method.getParameterCount() == 1;
    }

    private Object findBeanByType(Class<?> type) {
        for (Object bean : singletonBeans.values()) {
            if (type.isAssignableFrom(bean.getClass())) {
                return bean;
            }
        }
        return null;
    }

    public Object getBean(String name) {
        return singletonBeans.get(name);
    }
}
2. 测试用例:UserService 类
1
2
3
4
5
public class UserService {
    public void sayHello() {
        System.out.println("Hello, Mini Spring!");
    }
}
3. 测试用例:OrderService 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class OrderService {
    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void placeOrder() {
        System.out.println("Placing order...");
        userService.sayHello();
    }
}
4. 测试启动
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class TestMiniSpring {
    public static void main(String[] args) {
        MiniApplicationContext context = new MiniApplicationContext();
        context.registerBeanDefinition("userService", UserService.class);
        context.registerBeanDefinition("orderService", OrderService.class);
        context.refresh();
        
        OrderService orderService = (OrderService) context.getBean("orderService");
        orderService.placeOrder();
    }
}

V3.0版,在V2的基础上实现以下功能:

  • 支持构造器注入(Constructor Injection)
  • 支持自定义注解 @MiniAutowired,自动注入
  • 支持生命周期回调 afterPropertiesSet
  • 支持单例/多例(Scope管理)
  • 支持懒加载(Lazy Init)
1. 自定义注解 @MiniAutowired
1
2
3
4
5
6
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniAutowired {
}
2. BeanDefinition扩展
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class BeanDefinition {
    private Class<?> beanClass;
    private String scope = "singleton"; // 默认是单例
    private boolean lazyInit = false;   // 默认不是懒加载

    public BeanDefinition(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    // getter、setter 省略
    public Class<?> getBeanClass() {
        return beanClass;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public boolean isLazyInit() {
        return lazyInit;
    }

    public void setLazyInit(boolean lazyInit) {
        this.lazyInit = lazyInit;
    }
}
3. 生命周期接口(仿 Spring 的 InitializingBean)
1
2
3
public interface MiniInitializingBean {
    void afterPropertiesSet();
}
4. 核心改造 MiniApplicationContext
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import java.lang.reflect.*;
import java.util.*;

public class MiniApplicationContext {

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private Map<String, Object> singletonBeans = new HashMap<>();

    public void registerBeanDefinition(String name, Class<?> beanClass) {
        BeanDefinition definition = new BeanDefinition(beanClass);
        beanDefinitionMap.put(name, definition);
    }

    public void refresh() {
        // 提前实例化非懒加载且单例的Bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition definition = entry.getValue();
            if (!definition.isLazyInit() && "singleton".equals(definition.getScope())) {
                createBean(beanName, definition);
            }
        }
    }

    private Object createBean(String beanName, BeanDefinition definition) {
        if ("singleton".equals(definition.getScope()) && singletonBeans.containsKey(beanName)) {
            return singletonBeans.get(beanName);
        }

        try {
            Class<?> clazz = definition.getBeanClass();
            Object instance;

            // 优先找有 @MiniAutowired 注解的构造器
            Constructor<?>[] constructors = clazz.getDeclaredConstructors();
            Constructor<?> autowiredConstructor = null;
            for (Constructor<?> constructor : constructors) {
                if (constructor.isAnnotationPresent(MiniAutowired.class)) {
                    autowiredConstructor = constructor;
                    break;
                }
            }

            if (autowiredConstructor != null) {
                // 构造器注入
                Class<?>[] paramTypes = autowiredConstructor.getParameterTypes();
                Object[] params = new Object[paramTypes.length];
                for (int i = 0; i < paramTypes.length; i++) {
                    params[i] = findBeanByType(paramTypes[i]);
                }
                instance = autowiredConstructor.newInstance(params);
            } else {
                // 默认无参构造
                instance = clazz.getDeclaredConstructor().newInstance();
            }

            // 字段注入
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(MiniAutowired.class)) {
                    field.setAccessible(true);
                    Object dependency = findBeanByType(field.getType());
                    field.set(instance, dependency);
                }
            }

            // 调用afterPropertiesSet方法
            if (instance instanceof MiniInitializingBean) {
                ((MiniInitializingBean) instance).afterPropertiesSet();
            }

            // 单例池保存
            if ("singleton".equals(definition.getScope())) {
                singletonBeans.put(beanName, instance);
            }

            return instance;

        } catch (Exception e) {
            throw new RuntimeException("Failed to create bean: " + beanName, e);
        }
    }

private Object findBeanByType(Class<?> type) {
    System.out.println("DEBUG: Entering findBeanByType for type: " + type.getName());

    // 1. 优先从已存在的单例对象中查找
    for (Map.Entry<String, Object> entry : singletonMap.entrySet()) { // 注意这里遍历的是 singletonMap
        Object beanInstance = entry.getValue();
        if (type.isAssignableFrom(beanInstance.getClass())) {
            System.out.println("DEBUG: Found existing singleton bean '" + entry.getKey() + "' for type: " + type.getName());
            return beanInstance;
        }
    }

    // 2. 如果单例中没有找到,再遍历 BeanDefinitionMap,尝试按需创建或获取
    //    这里要特别小心处理循环依赖,如果直接 createBean 可能再次陷入循环
    //    在该场景中,如果 findBeanByType 每次都触发 createBean,那么当
    //    OrderService 正在创建时,它需要 UserService,
    //    如果 UserService 又需要 OrderService,就会循环。
    //    对于构造器注入的循环依赖,Mini Spring 需要更复杂的机制来处理。

    // 假设这里的目的是找到匹配类型且尚未创建的单例 Bean 定义,并创建它。
    // 但是,最简单且避免当前死循环的方法是,如果目标类型是单例且已存在,直接返回。
    // 如果是新的,再去创建。

    // 为了避免当前无限循环,至少需要确保 findBeanByType 不会重复触发正在创建的Bean的创建
    // 目前的 createBean 已经有 singletonMap.containsKey(beanName) 的检查,这是好的。
    // 但 findBeanByType 的遍历逻辑才是导致无限循环的根源。

    // 正确的查找流程应该大致是:
    // a. 查找已创建的单例
    // b. 查找是否有一个 BeanDefinition 匹配类型,且尚未创建(可能是懒加载的或者现在才被需要)
    // c. 如果找到这样的 BeanDefinition,再去 createBean

    // 这样调整 findBeanByType:
    String beanNameToCreate = null; // 找到第一个匹配类型的BeanDefinition
    for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
        BeanDefinition definition = entry.getValue();
        // type 是 bean.getClass() 的父类或父接口,或者与 bean.getClass() 是同一个类
        if (type.isAssignableFrom(definition.getBeanClass())) {
            // 确保这个BeanDefinition还没有在创建中或者已经完全创建
            if ("singleton".equals(definition.getScope()) && singletonMap.containsKey(entry.getKey())) {
                 // 已经存在于单例缓存中,但上面的循环应该已经找到了
                 // 如果执行到这里,说明前面的 singletonMap 遍历没找到,但这里又发现它已存在,是矛盾的。
                 // 这通常是设计上的冗余。
                 System.out.println("DEBUG: Found beanDefinition for type " + type.getName() + " and it's in singletonMap. Something is off.");
                 return singletonMap.get(entry.getKey()); // 但为了安全,还是返回
            }
            // 找到一个匹配类型但尚未完全创建的BeanDefinition
            beanNameToCreate = entry.getKey();
            break; // 找到第一个匹配的就够了
        }
    }

    if (beanNameToCreate != null) {
        System.out.println("DEBUG: Found bean definition '" + beanNameToCreate + "' for type: " + type.getName() + ". Attempting creation...");
        return createBean(beanNameToCreate, beanDefinitionMap.get(beanNameToCreate));
    }

    System.out.println("DEBUG: No bean found for type: " + type.getName());
    return null; // 或者抛出异常,表示找不到这个类型的Bean
}

    public Object getBean(String name) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition == null) {
            throw new RuntimeException("No bean named " + name);
        }
        if ("singleton".equals(definition.getScope())) {
            Object bean = singletonBeans.get(name);
            if (bean == null) {
                bean = createBean(name, definition);
            }
            return bean;
        } else {
            return createBean(name, definition);
        }
    }

    // 支持给BeanDefinition设定scope
    public void setScope(String name, String scope) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition != null) {
            definition.setScope(scope);
        }
    }

    // 支持给BeanDefinition设定懒加载
    public void setLazyInit(String name, boolean lazy) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition != null) {
            definition.setLazyInit(lazy);
        }
    }
}
6. 测试案例:UserService类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class UserService implements MiniInitializingBean {
    public void sayHello() {
        System.out.println("Hello from UserService");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("UserService afterPropertiesSet called!");
    }
}
7. OrderService(构造器注入)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class OrderService {

    private final UserService userService;

    @MiniAutowired
    public OrderService(UserService userService) {
        this.userService = userService;
    }

    public void placeOrder() {
        System.out.println("Order placed!");
        userService.sayHello();
    }
}
9. 测试启动
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class TestMiniSpring {
    public static void main(String[] args) {
        MiniApplicationContext context = new MiniApplicationContext();

        context.registerBeanDefinition("userService", UserService.class);
        context.registerBeanDefinition("orderService", OrderService.class);

        // 设置懒加载示范(比如OrderService懒加载)
        context.setLazyInit("orderService", true);

        context.refresh();

        System.out.println("---拿到OrderService---");
        OrderService orderService = (OrderService) context.getBean("orderService");
        orderService.placeOrder();
    }
}

V4.0版,实现组件扫描功能:

  • 组件扫描(Component Scan)
1.组件扫描(Component Scan)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import java.lang.annotation.*;

// ElementType.TYPE 表示你的注解只能用于任何“类型”的声明,“类型”在这里包括:类(Classes)、接口(Interfaces)、枚举(Enums)、注解(Annotation types)自身
// ElementType.FIELD:字段(包括枚举常量)
// ElementType.METHOD:方法
// ElementType.PARAMETER:方法参数
// ElementType.CONSTRUCTOR:构造函数
// ElementType.LOCAL_VARIABLE:局部变量
// ElementType.ANNOTATION_TYPE:注解类型(即用于修饰另一个注解)
// ElementType.PACKAGE:包
// ElementType.TYPE_PARAMETER:类型参数(Java 8+,例如 List<@MyAnnotation String> 中的 String)
// ElementType.TYPE_USE: 类型使用(Java 8+,例如 String @MyAnnotation [])

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniComponent {
}
2.在MiniApplicationContext中增加扫描指定包功能
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.io.File;
import java.net.URL;
import java.util.*;

public class MiniApplicationContext {

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private Map<String, Object> singletonBeans = new HashMap<>();

    public MiniApplicationContext(String basePackage) {
        scan(basePackage);
        refresh();
    }

    // 之前已有的 registerBeanDefinition(),refresh(),createBean()等保持不变

    private void scan(String basePackage) {
        String path = basePackage.replace('.', '/');
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL resource = classLoader.getResource(path);
        if (resource == null) {
            throw new RuntimeException("No resource found for package " + basePackage);
        }

        File baseDir = new File(resource.getFile());
        for (File file : Objects.requireNonNull(baseDir.listFiles())) {
            if (file.getName().endsWith(".class")) {
                String className = basePackage + '.' + file.getName().replace(".class", "");
                try {
                    Class<?> clazz = Class.forName(className);
                    if (clazz.isAnnotationPresent(MiniComponent.class)) {
                        String beanName = Introspector.decapitalize(clazz.getSimpleName());
                        registerBeanDefinition(beanName, clazz);
                    }
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}
3.定义一个被扫描的类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@MiniComponent
public class UserService implements MiniInitializingBean {
    public void sayHello() {
        System.out.println("UserService says: Hello!");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("UserService initialized via afterPropertiesSet");
    }
}
4.测试启动
1
2
3
4
5
6
7
public class TestScan {
    public static void main(String[] args) {
        MiniApplicationContext context = new MiniApplicationContext("com.example.demo");
        UserService userService = (UserService) context.getBean("userService");
        userService.sayHello();
    }
}

V5.0版,实现事件发布监听机制(Mini版 ApplicationEvent / ApplicationListener)功能:

  • 定义事件(MiniApplicationEvent):所有事件都继承它。
  • 定义监听器(MiniApplicationListener):所有监听器都实现它。
  • 定义事件发布器(MiniApplicationEventPublisher):容器在需要时负责发布事件。
  • 在容器启动时,扫描所有监听器,并保存下来。
  • 发布事件时,通知对应监听器。
1. 事件基类:MiniApplicationEvent
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class MiniApplicationEvent {
    private final Object source;

    public MiniApplicationEvent(Object source) {
        this.source = source;
    }

    public Object getSource() {
        return source;
    }
}
2. 监听器接口:MiniApplicationListener
1
2
3
public interface MiniApplicationListener<E extends MiniApplicationEvent> {
    void onApplicationEvent(E event);
}
3. 事件发布器接口:MiniApplicationEventPublisher
1
2
3
public interface MiniApplicationEventPublisher {
    void publishEvent(MiniApplicationEvent event);
}
4. 在容器(MiniApplicationContext)中集成
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
package com.yutao.minispring.v5;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yutao.minispring.v3.BeanDefinition;
import com.yutao.minispring.v3.MiniAutowired;
import com.yutao.minispring.v3.MiniInitializingBean;
import com.yutao.minispring.v4.MiniComponent;

public class MiniApplicationContext implements MiniApplicationEventPublisher {
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private Map<String, Object> singletonMap = new HashMap<>();
    private List<MiniApplicationListener<?>> applicationListeners = new ArrayList<>();

    public void registerBeanDefinition(String name, Class<?> beanClass) {
        BeanDefinition beanDefinition = new BeanDefinition(beanClass);
        beanDefinitionMap.put(name, beanDefinition);
    }

    public MiniApplicationContext(String basePackage) {
        scan(basePackage);
        refresh();
    }

    private void refresh() {
        for (String beanName : beanDefinitionMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if (!beanDefinition.isLazyInit() && "singleton".equals(beanDefinition.getScope())) {
                getBean(beanName);
            }
        }

        // 在 refresh 后,收集监听器
        for (Object bean : singletonMap.values()) {
            if (bean instanceof MiniApplicationListener) {
                applicationListeners.add((MiniApplicationListener<?>) bean);
            }
        }

        // 发布容器启动完成事件
        publishEvent(new MiniContextRefreshedEvent(this));
    }

    @Override
    public void publishEvent(MiniApplicationEvent event) {
        for (MiniApplicationListener<?> listener : applicationListeners) {
            if (supportsEvent(listener, event)) { // 新增的判断方法
                invokeListener(listener, event);
            }
        }
    }

    // 辅助方法:判断监听器是否支持处理某个事件
    private boolean supportsEvent(MiniApplicationListener<?> listener, MiniApplicationEvent event) {
        // 获取监听器接口的泛型参数类型
        // 这是一个相对复杂但非常重要的反射操作
        try {
            // 获取 MiniApplicationListener 接口
            // 如果 listener 是 CustomEventListener 的实例,那么 listener.getClass().getGenericInterfaces() 会返回一个 Type 数组,其中包含一个表示 MiniApplicationListener<MiniCustomEvent> 的 ParameterizedType 对象。
            // 如果 listener 是 ContextRefreshListener 的实例,那么它会返回一个包含表示 MiniApplicationListener<MiniContextRefreshedEvent> 的 ParameterizedType 对象。
            java.lang.reflect.Type[] genericInterfaces = listener.getClass().getGenericInterfaces();
            for (java.lang.reflect.Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof java.lang.reflect.ParameterizedType) {
                    // if 块的外部,genericInterface 变量的静态类型(也就是编译器在编译时看到的类型)仍然是 java.lang.reflect.Type
                    // 为了让编译器知道你确实知道 genericInterface 在这里是一个 ParameterizedType,并且你想要使用
                    // ParameterizedType 独有的方法,你就必须进行强制类型转换 (Type Casting)
                    java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) genericInterface;
                    if (pt.getRawType().equals(MiniApplicationListener.class)) { // 确保是 MiniApplicationListener 接口
                        java.lang.reflect.Type eventType = pt.getActualTypeArguments()[0]; // 获取泛型参数 E

                        // 将 Type 转换为 Class
                        Class<?> eventClass;
                        if (eventType instanceof Class) {
                            eventClass = (Class<?>) eventType;
                        } else if (eventType instanceof java.lang.reflect.WildcardType) { // 处理
                                                                                          // MiniApplicationListener<?>
                                                                                          // 这样的通配符
                            eventClass = (Class<?>) ((java.lang.reflect.WildcardType) eventType).getUpperBounds()[0];
                        } else {
                            // 无法识别的类型,默认不支持
                            return false;
                        }

                        // 判断当前事件的类型是否是监听器期望事件类型的子类或本身
                        // event.getClass() 获取实际事件的类
                        // eventClass 是监听器声明要处理的类
                        return eventClass.isAssignableFrom(event.getClass());
                    }
                }
            }
        } catch (Exception e) {
            // 捕获反射异常,例如类加载器问题,通常不会发生
            System.err
                    .println("SCAN_ERROR: 处理监听器类型时发生异常: " + listener.getClass().getName() + ", 错误: " + e.getMessage());
            return false;
        }
        return false; // 如果找不到泛型信息,默认不支持
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void invokeListener(MiniApplicationListener listener, MiniApplicationEvent event) {
        listener.onApplicationEvent(event);
    }

    private Object findBeanByType(Class<?> type) {
        System.out.println("DEBUG: Entering findBeanByType for type: " + type.getName());

        // 1. 优先从已存在的单例对象中查找
        for (Map.Entry<String, Object> entry : singletonMap.entrySet()) { // 注意这里遍历的是 singletonMap
            Object beanInstance = entry.getValue();
            if (type.isAssignableFrom(beanInstance.getClass())) {
                System.out.println(
                        "DEBUG: Found existing singleton bean '" + entry.getKey() + "' for type: " + type.getName());
                return beanInstance;
            }
        }

        // 2. 如果单例中没有找到,再遍历 BeanDefinitionMap,尝试按需创建或获取
        // 这里要特别小心处理循环依赖,如果直接 createBean 可能再次陷入循环
        // 在你的场景中,如果 findBeanByType 每次都触发 createBean,那么当
        // OrderService 正在创建时,它需要 UserService,
        // 如果 UserService 又需要 OrderService,就会循环。
        // 对于构造器注入的循环依赖,Mini Spring 需要更复杂的机制来处理。

        // 假设你这里的目的是找到匹配类型且尚未创建的单例 Bean 定义,并创建它。
        // 但是,最简单且避免当前死循环的方法是,如果目标类型是单例且已存在,直接返回。
        // 如果是新的,再去创建。

        // 为了避免当前无限循环,你至少需要确保 findBeanByType 不会重复触发正在创建的Bean的创建
        // 目前的 createBean 已经有 singletonMap.containsKey(beanName) 的检查,这是好的。
        // 但 findBeanByType 的遍历逻辑才是导致无限循环的根源。

        // 正确的查找流程应该大致是:
        // a. 查找已创建的单例
        // b. 查找是否有一个 BeanDefinition 匹配类型,且尚未创建(可能是懒加载的或者现在才被需要)
        // c. 如果找到这样的 BeanDefinition,再去 createBean

        // 让我们这样调整 findBeanByType:
        String beanNameToCreate = null; // 找到第一个匹配类型的BeanDefinition
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            BeanDefinition definition = entry.getValue();
            if (type.isAssignableFrom(definition.getBeanClass())) {
                // 确保这个BeanDefinition还没有在创建中或者已经完全创建
                if ("singleton".equals(definition.getScope()) && singletonMap.containsKey(entry.getKey())) {
                    // 已经存在于单例缓存中,但上面的循环应该已经找到了
                    // 如果执行到这里,说明前面的 singletonMap 遍历没找到,但这里又发现它已存在,是矛盾的。
                    // 这通常是设计上的冗余。
                    System.out.println("DEBUG: Found beanDefinition for type " + type.getName()
                            + " and it's in singletonMap. Something is off.");
                    return singletonMap.get(entry.getKey()); // 但为了安全,还是返回
                }
                // 找到一个匹配类型但尚未完全创建的BeanDefinition
                beanNameToCreate = entry.getKey();
                break; // 找到第一个匹配的就够了
            }
        }

        if (beanNameToCreate != null) {
            System.out.println("DEBUG: Found bean definition '" + beanNameToCreate + "' for type: " + type.getName()
                    + ". Attempting creation...");
            return createBean(beanNameToCreate, beanDefinitionMap.get(beanNameToCreate));
        }

        System.out.println("DEBUG: No bean found for type: " + type.getName());
        return null; // 或者抛出异常,表示找不到这个类型的Bean
    }

    // 支持给BeanDefinition设定scope
    public void setScope(String name, String scope) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition != null) {
            definition.setScope(scope);
        }
    }

    // 支持给BeanDefinition设定懒加载
    public void setLazyInit(String name, boolean lazy) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition != null) {
            definition.setLazyInit(lazy);
        }
    }

    /**
     * 扫描指定包路径下的类,查找并注册带有 @MiniComponent 注解的 Bean 定义。
     * 目前仅扫描指定包的直接子级,不进行递归扫描子包。
     *
     * @param basePackage 要扫描的基础包名,例如 "com.yutao.minispring.v4"
     */
    private void scan(String basePackage) {
        // 1. 打印扫描开始的调试信息
        System.out.println("SCAN_DEBUG: 开始扫描基础包: " + basePackage);

        // 2. 将包名转换为文件系统路径 (例如 com.example.app -> com/example/app)
        String path = basePackage.replace('.', '/');
        System.out.println("SCAN_DEBUG: 转换后的包路径: " + path);

        // 3. 获取当前线程的类加载器,用于查找资源
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        // 4. 通过类加载器获取包路径对应的 URL 资源
        URL resource = classLoader.getResource(path);

        // 5. 检查资源是否找到,如果没找到则抛出运行时异常
        if (resource == null) {
            System.err.println("SCAN_ERROR: 未找到基础包资源: " + basePackage + "。这很可能是导致问题的原因!");
            throw new RuntimeException("未找到包资源: " + basePackage);
        }
        System.out.println("SCAN_DEBUG: 找到的资源URL: " + resource.toString());

        // 6. 将 URL 资源转换为 File 对象,表示目录
        File baseDir = null;
        try {
            // 尝试使用 resource.toURI() 转换为 URI 再创建 File,以更好地处理路径中的空格或特殊字符
            baseDir = new File(resource.toURI());
        } catch (Exception e) {
            // 如果转换失败,打印错误信息并抛出异常
            System.err.println("SCAN_ERROR: 无法将资源URL转换为文件URI: " + resource.toString() + "。错误: " + e.getMessage());
            e.printStackTrace(); // 打印完整的堆栈跟踪以便调试
            throw new RuntimeException("无法获取包的基础目录: " + basePackage, e);
        }

        System.out.println("SCAN_DEBUG: 扫描基础目录: " + baseDir.getAbsolutePath());

        // 7. 检查 baseDir 是否存在且是一个目录
        if (!baseDir.exists() || !baseDir.isDirectory()) {
            System.err.println("SCAN_ERROR: 基础目录不存在或不是一个目录: " + baseDir.getAbsolutePath() + "。这是一个严重的扫描问题。");
            throw new RuntimeException("扫描基础目录无效: " + baseDir.getAbsolutePath());
        }

        // 8. 列出目录中的所有文件和子目录
        File[] files = baseDir.listFiles();
        // 9. 如果列出文件失败(例如权限问题或不是真实目录),则抛出异常
        if (files == null) {
            System.err.println("SCAN_ERROR: 无法列出目录文件: " + baseDir.getAbsolutePath() + "。目录可能无法访问或不是实际目录(例如在 JAR 包内部)。");
            throw new RuntimeException("无法列出目录文件: " + baseDir.getAbsolutePath());
        }
        System.out.println("SCAN_DEBUG: 找到的文件/目录数量: " + files.length);

        // 10. 遍历目录中的每个文件或子目录
        for (File file : files) {
            System.out.println("SCAN_DEBUG: 正在处理文件/目录: " + file.getName());

            // 11. 如果是子目录,当前实现是跳过(不进行递归扫描)
            if (file.isDirectory()) {
                System.out.println("SCAN_DEBUG: 跳过子目录(当前未实现递归扫描): " + file.getName());
                continue; // 跳过当前循环,处理下一个文件
            }

            // 12. 检查文件是否以 ".class" 结尾(表示是一个编译后的 Java 类文件)
            if (file.getName().endsWith(".class")) {
                // 13. 构建完整的类名 (例如 com.yutao.minispring.v4.UserService)
                String className = basePackage + '.' + file.getName().replace(".class", "");
                System.out.println("SCAN_DEBUG: 尝试加载类: " + className);

                try {
                    // 14. 使用 Class.forName() 加载类
                    Class<?> clazz = Class.forName(className);
                    System.out.println("SCAN_DEBUG: 成功加载类: " + clazz.getName());

                    // 15. 检查加载的类是否带有 @MiniComponent 注解
                    if (clazz.isAnnotationPresent(MiniComponent.class)) {
                        // 16. 如果有注解,生成 Bean 名称(通常是类名首字母小写)
                        String beanName = Introspector.decapitalize(clazz.getSimpleName());
                        System.out.println("SCAN_DEBUG: 发现带有 @MiniComponent 注解的类: " + clazz.getName()
                                + ",计算出的 Bean 名称: " + beanName);
                        // 17. 注册 Bean 定义
                        registerBeanDefinition(beanName, clazz);
                    } else {
                        System.out.println("SCAN_DEBUG: 类 " + clazz.getName() + " 未找到 @MiniComponent 注解。");
                    }
                } catch (ClassNotFoundException e) {
                    // 18. 捕获类未找到异常,打印错误信息
                    System.err.println("SCAN_ERROR: 扫描时未找到类: " + className + "。错误: " + e.getMessage());
                    // 通常这里不会重新抛出,除非你希望任何一个类加载失败都中断扫描
                    // throw new RuntimeException(e); // 如果需要严格处理,可以重新抛出
                } catch (Exception e) {
                    // 19. 捕获其他在类处理过程中可能发生的异常
                    System.err.println("SCAN_ERROR: 处理类 " + className + " 时发生意外错误: " + e.getMessage());
                    e.printStackTrace(); // 打印堆栈跟踪以便调试
                }
            } else {
                System.out.println("SCAN_DEBUG: 跳过非 .class 文件: " + file.getName());
            }
        }
        // 20. 打印扫描完成的调试信息
        System.out.println("SCAN_DEBUG: 基础包扫描完成: " + basePackage);
        System.out.println("SCAN_DEBUG: 扫描后 beanDefinitionMap 大小: " + beanDefinitionMap.size());
        // 21. 打印所有已注册的 Bean 名称
        beanDefinitionMap.keySet().forEach(name -> System.out.println("SCAN_DEBUG: 已注册的 Bean: " + name));
    }
    public Object getBean(String name) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition == null) {
            throw new RuntimeException("No bean named " + name);
        }
        if ("singleton".equals(definition.getScope())) {
            Object bean = singletonMap.get(name);
            if (bean == null) {
                bean = createBean(name, definition);
            }
            return bean;
        } else {
            return createBean(name, definition);
        }
    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        System.out.println("DEBUG: Entering createBean for: " + beanName);
        if ("singleton".equals(beanDefinition.getScope()) && singletonMap.containsKey(beanName)) {
            return singletonMap.get(beanName);
        }

        try {
            Class<?> clazz = beanDefinition.getBeanClass();
            Object instance;

            Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
            Constructor<?> autowiredConstructor = null;

            for (Constructor<?> constructor : declaredConstructors) {
                if (constructor.isAnnotationPresent(MiniAutowired.class)) {
                    autowiredConstructor = constructor;
                    break;
                }
            }

            if (autowiredConstructor != null) {
                Class<?>[] parameterTypes = autowiredConstructor.getParameterTypes();
                Object[] params = new Object[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    params[i] = findBeanByType(parameterTypes[i]);
                }
                instance = autowiredConstructor.newInstance(params);
            } else {
                instance = clazz.getDeclaredConstructor().newInstance();
            }

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(MiniAutowired.class)) {
                    field.setAccessible(true);
                    Object dependency = findBeanByType(field.getType());
                    field.set(instance, dependency);
                }
            }

            if (instance instanceof MiniInitializingBean) {
                ((MiniInitializingBean) instance).afterPropertiesSet();
            }

            if ("singleton".equals(beanDefinition.getScope())) {
                singletonMap.put(beanName, instance);
            }

            System.out.println("DEBUG: Exiting createBean for: " + beanName);
            return instance;

        } catch (Exception e) {
            throw new RuntimeException("Failed to create bean: " + beanName, e);
        }
    }
}
5. 定义一个具体事件:MiniContextRefreshedEvent
1
2
3
4
5
public class MiniContextRefreshedEvent extends MiniApplicationEvent {
    public MiniContextRefreshedEvent(Object source) {
        super(source);
    }
}
6. 定义一个监听器示例
1
2
3
4
5
6
7
@MiniComponent
public class ContextRefreshListener implements MiniApplicationListener<MiniContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(MiniContextRefreshedEvent event) {
        System.out.println("容器刷新完成!收到 MiniContextRefreshedEvent!");
    }
}
7. 定义监听自定义事件监听器
1
2
3
4
5
6
7
8
9
@MiniComponent
public class CustomEventListener implements MiniApplicationListener<MiniCustomEvent> {

    @Override
    public void onApplicationEvent(MiniCustomEvent event) {
        System.out.println("收到事件:" + event);
    }

}
8. 手动自定义个事件
1
2
3
4
5
public class MiniCustomEvent extends MiniApplicationEvent {
    public MiniCustomEvent(Object source) {
        super(source);
    }
}
9. 测试启动
1
2
3
4
5
6
7
8
9
public class TestEvent {
    public static void main(String[] args) {
        MiniApplicationContext context = new MiniApplicationContext("com.example.demo");
        // 自动打印:"容器刷新完成!收到 MiniContextRefreshedEvent!"

        // 手动发布一个事件
        context.publishEvent(new MiniCustomEvent(context));
    }
}

V6.0版本,实现面向切面编程(AOP)功能:

  • 定义 AOP 核心注解(@MiniAspect)
  • 定义方法拦截器接口(MiniMethodInterceptor)
  • 实现代理工厂(MiniProxyFactory)(支持 JDK + CGLIB 两种)
  • 容器中集成 AOP 支持(wrapIfNeeded)
  • 定义业务Bean测试(带不带接口都行)
  • 测试:接口类+普通类代理
1. 定义 AOP 核心注解
1
2
3
4
5
6
import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniAspect {
}
2. 定义方法拦截器接口
1
2
3
4
5
import java.lang.reflect.Method;

public interface MiniMethodInterceptor {
    Object invoke(Method method, Object[] args, Object target) throws Throwable;
}
3. 实现代理工厂(JDK + CGLIB)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.yutao.minispring.v6;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class MiniProxyFactory {

    public static Object createProxy(Object target, MiniMethodInterceptor interceptor) {
        Class<?> targetClass = target.getClass();

        if (targetClass.getInterfaces().length > 0) {
            System.out.println("[MiniProxyFactory] 使用 JDK 动态代理为 " + targetClass.getSimpleName() + " 创建代理。");
            return Proxy.newProxyInstance(
                    targetClass.getClassLoader(),
                    targetClass.getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        // Object proxy, 这个参数就是 Proxy.newProxyInstance() 方法返回的那个代理实例本身
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("[DEBUG-PROXY] JDK InvocationHandler.invoke called for method: "
                                    + method.getName()); // <-- 调试输出
                            return interceptor.invoke(method, args, target);
                        }
                    });
        } else {
            System.out.println("[MiniProxyFactory] 使用 CGLIB 动态代理为 " + targetClass.getSimpleName() + " 创建代理。");
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(targetClass);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                // obj 就是 CGLIB 生成的代理对象
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)
                        throws Throwable {
                    System.out.println(
                            "[DEBUG-PROXY] CGLIB MethodInterceptor.intercept called for method: " + method.getName()); // <--
                                                                                                                       // 调试输出
                    System.out.println("[MiniAOP] Before method: " + method.getName() + " (via CGLIB)");
                    Object result = methodProxy.invokeSuper(obj, args);
                    System.out.println("[MiniAOP] After method: " + method.getName() + " (via CGLIB)");
                    return result;
                }
            });
            return enhancer.create();
        }
    }
}
4. 容器中集成(修改 MiniApplicationContext)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
package com.yutao.minispring.v6;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yutao.minispring.v3.BeanDefinition;
import com.yutao.minispring.v3.MiniAutowired;
import com.yutao.minispring.v3.MiniInitializingBean;
import com.yutao.minispring.v4.MiniComponent;
import com.yutao.minispring.v5.MiniApplicationEvent;
import com.yutao.minispring.v5.MiniApplicationEventPublisher;
import com.yutao.minispring.v5.MiniApplicationListener;
import com.yutao.minispring.v5.MiniContextRefreshedEvent;

public class MiniApplicationContext implements MiniApplicationEventPublisher {
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private Map<String, Object> singletonMap = new HashMap<>();
    private List<MiniApplicationListener<?>> applicationListeners = new ArrayList<>();

    public void registerBeanDefinition(String name, Class<?> beanClass) {
        BeanDefinition beanDefinition = new BeanDefinition(beanClass);
        beanDefinitionMap.put(name, beanDefinition);
    }

    public MiniApplicationContext(String basePackage) {
        scan(basePackage);
        refresh();
    }

    private void refresh() {
        for (String beanName : beanDefinitionMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if (!beanDefinition.isLazyInit() && "singleton".equals(beanDefinition.getScope())) {
                getBean(beanName);
            }
        }

        // 在 refresh 后,收集监听器
        for (Object bean : singletonMap.values()) {
            // 注意:这里收集的 bean 可能是代理对象,但其原始类型仍然是 MiniApplicationListener
            // 这在 Spring 中是正常行为,代理对象会实现所有原始接口。
            if (bean instanceof MiniApplicationListener) {
                applicationListeners.add((MiniApplicationListener<?>) bean);
            }
        }

        // 发布容器启动完成事件
        publishEvent(new MiniContextRefreshedEvent(this));
    }

    @Override
    public void publishEvent(MiniApplicationEvent event) {
        for (MiniApplicationListener<?> listener : applicationListeners) {
            if (supportsEvent(listener, event)) { // 新增的判断方法
                invokeListener(listener, event);
            }
        }
    }

    // 辅助方法:判断监听器是否支持处理某个事件
    private boolean supportsEvent(MiniApplicationListener<?> listener, MiniApplicationEvent event) {
        try {
            java.lang.reflect.Type[] genericInterfaces = listener.getClass().getGenericInterfaces();
            for (java.lang.reflect.Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof java.lang.reflect.ParameterizedType) {
                    java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) genericInterface;
                    if (pt.getRawType().equals(MiniApplicationListener.class)) {
                        java.lang.reflect.Type eventType = pt.getActualTypeArguments()[0];

                        Class<?> eventClass;
                        if (eventType instanceof Class) {
                            eventClass = (Class<?>) eventType;
                        } else if (eventType instanceof java.lang.reflect.WildcardType) {
                            eventClass = (Class<?>) ((java.lang.reflect.WildcardType) eventType).getUpperBounds()[0];
                        } else {
                            return false;
                        }
                        return eventClass.isAssignableFrom(event.getClass());
                    }
                }
            }
        } catch (Exception e) {
            System.err
                    .println("SCAN_ERROR: 处理监听器类型时发生异常: " + listener.getClass().getName() + ", 错误: " + e.getMessage());
            return false;
        }
        return false;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void invokeListener(MiniApplicationListener listener, MiniApplicationEvent event) {
        listener.onApplicationEvent(event);
    }

    private Object findBeanByType(Class<?> type) {
        System.out.println("DEBUG: Entering findBeanByType for type: " + type.getName());

        for (Map.Entry<String, Object> entry : singletonMap.entrySet()) {
            Object beanInstance = entry.getValue();
            if (type.isAssignableFrom(beanInstance.getClass())) {
                System.out.println(
                        "DEBUG: Found existing singleton bean '" + entry.getKey() + "' for type: " + type.getName());
                return beanInstance;
            }
        }

        String beanNameToCreate = null;
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            BeanDefinition definition = entry.getValue();
            if (type.isAssignableFrom(definition.getBeanClass())) {
                if ("singleton".equals(definition.getScope()) && singletonMap.containsKey(entry.getKey())) {
                    System.out.println("DEBUG: Found beanDefinition for type " + type.getName()
                            + " and it's in singletonMap. Something is off.");
                    return singletonMap.get(entry.getKey());
                }
                beanNameToCreate = entry.getKey();
                break;
            }
        }

        if (beanNameToCreate != null) {
            System.out.println("DEBUG: Found bean definition '" + beanNameToCreate + "' for type: " + type.getName()
                    + ". Attempting creation...");
            return createBean(beanNameToCreate, beanDefinitionMap.get(beanNameToCreate));
        }

        System.out.println("DEBUG: No bean found for type: " + type.getName());
        return null;
    }

    public void setScope(String name, String scope) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition != null) {
            definition.setScope(scope);
        }
    }

    public void setLazyInit(String name, boolean lazy) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition != null) {
            definition.setLazyInit(lazy);
        }
    }

    /**
     * 扫描指定包路径下的类,查找并注册带有 @MiniComponent 注解的 Bean 定义。
     * 目前仅扫描指定包的直接子级,不进行递归扫描子包。
     *
     * @param basePackage 要扫描的基础包名,例如 "com.yutao.minispring.v6"
     */
    private void scan(String basePackage) {
        System.out.println("SCAN_DEBUG: 开始扫描基础包: " + basePackage);
        String path = basePackage.replace('.', '/');
        System.out.println("SCAN_DEBUG: 转换后的包路径: " + path);
        // Java 的原则是:每个线程都有一个与之关联的“上下文类加载器”(Context ClassLoader)
        // 这不意味着每个线程都拥有一个自己独有的类加载器实例
        // 而是说每个线程都可以设置或获取一个默认的类加载器,供该线程中运行的代码(尤其是框架和库代码)使用,以便在运行时加载类和资源
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL resource = classLoader.getResource(path);
        if (resource == null) {
            System.err.println("SCAN_ERROR: 未找到基础包资源: " + basePackage + "。这很可能是导致问题的原因!");
            throw new RuntimeException("未找到包资源: " + basePackage);
        }
        System.out.println("SCAN_DEBUG: 找到的资源URL: " + resource.toString());
        File baseDir = null;
        try {
            baseDir = new File(resource.toURI());
        } catch (Exception e) {
            System.err.println("SCAN_ERROR: 无法将资源URL转换为文件URI: " + resource.toString() + "。错误: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("无法获取包的基础目录: " + basePackage, e);
        }
        System.out.println("SCAN_DEBUG: 扫描基础目录: " + baseDir.getAbsolutePath());
        if (!baseDir.exists() || !baseDir.isDirectory()) {
            System.err.println("SCAN_ERROR: 基础目录不存在或不是一个目录: " + baseDir.getAbsolutePath() + "。这是一个严重的扫描问题。");
            throw new RuntimeException("扫描基础目录无效: " + baseDir.getAbsolutePath());
        }
        File[] files = baseDir.listFiles();
        if (files == null) {
            System.err.println("SCAN_ERROR: 无法列出目录文件: " + baseDir.getAbsolutePath() + "。目录可能无法访问或不是实际目录(例如在 JAR 包内部)。");
            throw new RuntimeException("无法列出目录文件: " + baseDir.getAbsolutePath());
        }
        System.out.println("SCAN_DEBUG: 找到的文件/目录数量: " + files.length);
        for (File file : files) {
            System.out.println("SCAN_DEBUG: 正在处理文件/目录: " + file.getName());
            if (file.isDirectory()) {
                System.out.println("SCAN_DEBUG: 跳过子目录(当前未实现递归扫描): " + file.getName());
                continue;
            }
            if (file.getName().endsWith(".class")) {
                String className = basePackage + '.' + file.getName().replace(".class", "");
                System.out.println("SCAN_DEBUG: 尝试加载类: " + className);
                try {
                    Class<?> clazz = Class.forName(className);
                    System.out.println("SCAN_DEBUG: 成功加载类: " + clazz.getName());
                    if (clazz.isAnnotationPresent(MiniComponent.class)) {
                        String beanName = Introspector.decapitalize(clazz.getSimpleName());
                        System.out.println("SCAN_DEBUG: 发现带有 @MiniComponent 注解的类: " + clazz.getName()
                                + ",计算出的 Bean 名称: " + beanName);
                        registerBeanDefinition(beanName, clazz);
                    } else {
                        System.out.println("SCAN_DEBUG: 类 " + clazz.getName() + " 未找到 @MiniComponent 注解。");
                    }
                } catch (ClassNotFoundException e) {
                    System.err.println("SCAN_ERROR: 扫描时未找到类: " + className + "。错误: " + e.getMessage());
                } catch (Exception e) {
                    System.err.println("SCAN_ERROR: 处理类 " + className + " 时发生意外错误: " + e.getMessage());
                    e.printStackTrace();
                }
            } else {
                System.out.println("SCAN_DEBUG: 跳过非 .class 文件: " + file.getName());
            }
        }
        System.out.println("SCAN_DEBUG: 基础包扫描完成: " + basePackage);
        System.out.println("SCAN_DEBUG: 扫描后 beanDefinitionMap 大小: " + beanDefinitionMap.size());
        beanDefinitionMap.keySet().forEach(name -> System.out.println("SCAN_DEBUG: 已注册的 Bean: " + name));
    }

    public Object getBean(String name) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition == null) {
            throw new RuntimeException("No bean named " + name);
        }
        if ("singleton".equals(definition.getScope())) {
            Object bean = singletonMap.get(name);
            if (bean == null) {
                bean = createBean(name, definition);
            }
            return bean;
        } else {
            return createBean(name, definition);
        }
    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        System.out.println("DEBUG: Entering createBean for: " + beanName);
        if ("singleton".equals(beanDefinition.getScope()) && singletonMap.containsKey(beanName)) {
            return singletonMap.get(beanName);
        }

        try {
            Class<?> clazz = beanDefinition.getBeanClass();
            Object instance;

            Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
            Constructor<?> autowiredConstructor = null;

            for (Constructor<?> constructor : declaredConstructors) {
                if (constructor.isAnnotationPresent(MiniAutowired.class)) {
                    autowiredConstructor = constructor;
                    break;
                }
            }

            if (autowiredConstructor != null) {
                Class<?>[] parameterTypes = autowiredConstructor.getParameterTypes();
                Object[] params = new Object[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    params[i] = findBeanByType(parameterTypes[i]);
                }
                instance = autowiredConstructor.newInstance(params);
            } else {
                instance = clazz.getDeclaredConstructor().newInstance();
            }

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(MiniAutowired.class)) {
                    field.setAccessible(true);
                    Object dependency = findBeanByType(field.getType());
                    field.set(instance, dependency);
                }
            }

            if (instance instanceof MiniInitializingBean) {
                ((MiniInitializingBean) instance).afterPropertiesSet();
            }

            // 检查是否需要AOP代理
            Object proxiedInstance = wrapIfNeeded(instance); 

            if ("singleton".equals(beanDefinition.getScope())) {
                singletonMap.put(beanName, proxiedInstance);
            }

            System.out.println("DEBUG: Exiting createBean for: " + beanName);
            return proxiedInstance; // <-- 关键修改:返回代理对象

        } catch (Exception e) {
            throw new RuntimeException("Failed to create bean: " + beanName, e);
        }
    }

    private Object wrapIfNeeded(Object bean) {
        Class<?> clazz = bean.getClass();
        if (clazz.isAnnotationPresent(MiniAspect.class)) {
            System.out.println("DEBUG: wrapIfNeeded 发现 @MiniAspect 注解,尝试创建代理 for: " + clazz.getSimpleName());
            return MiniProxyFactory.createProxy(bean, new MiniMethodInterceptor() {
                @Override
                public Object invoke(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println(
                            "[DEBUG-INTERCEPTOR] MiniMethodInterceptor.invoke called for method: " + method.getName());
                    System.out.println("[MiniAOP] Before method: " + method.getName());
                    Object result = method.invoke(target, args); // JDK 代理会执行到这里
                    System.out.println("[MiniAOP] After method: " + method.getName());
                    return result;
                }
            });
        }
        System.out.println("DEBUG: wrapIfNeeded 未发现 @MiniAspect 注解,返回原始 Bean: " + clazz.getSimpleName());
        return bean;
    }
}
5. 测试案例:带接口的业务Bean(走 JDK代理)
1
2
3
public interface IOrderService {
    void createOrder();
}

实现:

1
2
3
4
5
6
7
8
@MiniComponent
@MiniAspect
public class OrderService implements IOrderService {
    @Override
    public void createOrder() {
        System.out.println("创建订单...");
    }
}
6. 测试案例:没有接口的业务Bean(走 CGLIB代理)
1
2
3
4
5
6
7
@MiniComponent
@MiniAspect
public class UserService {
    public void registerUser() {
        System.out.println("注册用户...");
    }
}
7. 测试启动
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

public class TestAop {
    public static void main(String[] args) {
        // 打印 JVM 参数的值,验证是否生效
        String saveGeneratedFiles = System.getProperty("sun.misc.ProxyGenerator.saveGeneratedFiles");
        System.out.println("DEBUG: JVM property 'sun.misc.ProxyGenerator.saveGeneratedFiles' = " + saveGeneratedFiles);

        // 打印当前 Java 进程的工作目录
        String userDir = System.getProperty("user.dir");
        System.out.println("DEBUG: Current working directory (user.dir) = " + userDir);

        MiniApplicationContext context = new MiniApplicationContext("com.yutao.minispring.v6");

        IOrderService orderService = (IOrderService) context.getBean("orderService");
        System.out.println("DEBUG: orderService 实际运行时类: " + orderService.getClass().getName());
        orderService.createOrder();

        UserService userService = (UserService) context.getBean("userService");
        System.out.println("DEBUG: userService 实际运行时类: " + userService.getClass().getName());
        userService.registerUser();
    }
}

在V7.0,在v6的基础上实现以下功能:

  • 支持 切点表达式(Pointcut)
  • 支持 前置通知、后置通知、异常通知
  • 支持 环绕通知(Around)
  • 支持 MiniJoinPoint 参数传递
1. AOP 注解体系升级
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 标记一个切面类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniAspect {
}

// 标记一个切点方法
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniPointcut {
    String value(); // 支持方法名匹配,简单版
}

// 标记前置通知
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniBefore {
    String value();
}

// 标记后置通知
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniAfter {
    String value();
}

// 标记异常通知
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniAfterThrowing {
    String value();
}

// 标记环绕通知
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MiniAround {
    String value();
}

// 表示AOP后置返回通知的注解
@Target(ElementType.METHOD) // 此注解只能应用于方法
@Retention(RetentionPolicy.RUNTIME) // 此注解在运行时可见,以便通过反射进行处理
public @interface MiniAfterReturning {
    String value(); // 定义一个value属性,用于指定切点名称
}
2. 定义连接点MiniJoinPoint,(类似 Spring的 `ProceedingJoinPoint`)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.yutao.minispring.v7;

import java.lang.reflect.Method;
import java.util.List;

public class MiniJoinPoint {
    private Method method; // 被拦截的目标方法(例如 OrderService.createOrder)
    private Object[] args; // 调用目标方法时传入的参数
    private Object target; // 原始的目标对象实例(例如 OrderService 的实例)
    // 新增:用于存储适用于当前方法调用的切面执行器链
    private List<MiniAspectExecutor> interceptors;
    // 新增:当前执行到的拦截器在链中的索引
    private int currentInterceptorIndex;

    // 构造函数:用于 AopMethodInterceptor 初始化链
    public MiniJoinPoint(Method method, Object[] args, Object target, List<MiniAspectExecutor> interceptors) {
        this.method = method;
        this.args = args;
        this.target = target;
        this.interceptors = interceptors;
        this.currentInterceptorIndex = -1; // 初始索引设为 -1,表示在第一个拦截器之前
    }

    // 私有构造函数:用于在 proceed() 中递归调用链中的下一个拦截器
    private MiniJoinPoint(Method method, Object[] args, Object target, List<MiniAspectExecutor> interceptors,
            int index) {
        this.method = method;
        this.args = args;
        this.target = target;
        this.interceptors = interceptors;
        this.currentInterceptorIndex = index;
    }

    // 核心方法:继续执行链中的下一个元素(下一个拦截器或原始目标方法)
    public Object proceed() throws Throwable {
        // 如果链中还有下一个拦截器
        if (currentInterceptorIndex < interceptors.size() - 1) {
            // 创建一个新的 MiniJoinPoint 实例,指向链中的下一个拦截器
            MiniJoinPoint nextJoinPoint = new MiniJoinPoint(method, args, target, interceptors,
                    currentInterceptorIndex + 1);
            MiniAspectExecutor nextExecutor = interceptors.get(currentInterceptorIndex + 1);
            // 调用下一个拦截器(MiniAspectExecutor)的 invoke 方法
            // 这样就实现了 AOP 链的递归调用
            return nextExecutor.invoke(nextJoinPoint);
        } else {
            // 如果链中没有更多拦截器了,则执行原始目标方法
            System.out.println("DEBUG: MiniJoinPoint.proceed() 调用原始目标方法: " + method.getName());
            return method.invoke(target, args);
        }
    }

    public Method getMethod() {
        return method;
    }

    public Object[] getArgs() {
        return args;
    }

    public Object getTarget() {
        return target;
    }
}
4. 定义切面 LogAspect
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.yutao.minispring.v7;

import com.yutao.minispring.v4.MiniComponent; // 导入 MiniComponent 注解

@MiniAspect
@MiniComponent // FIX: 添加 @MiniComponent,以便 MiniApplicationContext 能够扫描并将其注册为 Bean
public class LogAspect {

    // 切点定义:匹配 createOrder 方法
    @MiniPointcut("createOrder")
    public void createOrderPointcut() {
        // 切点方法本身通常不需要实现,其作用是承载 @MiniPointcut 注解
    }

    // 切点定义:匹配 registerUser 方法
    @MiniPointcut("registerUser")
    public void registerUserPointcut() {
    }

    // 1. @MiniBefore 前置通知
    @MiniBefore("createOrder")
    public void beforeCreateOrder(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: Before method: " + joinPoint.getMethod().getName());
    }

    @MiniBefore("registerUser")
    public void beforeRegisterUser(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: Before method: " + joinPoint.getMethod().getName());
    }

    // 2. @MiniAfter 后置通知 (无论成功失败都会执行)
    @MiniAfter("createOrder")
    public void afterCreateOrder(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: After method: " + joinPoint.getMethod().getName());
    }

    @MiniAfter("registerUser")
    public void afterRegisterUser(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: After method: " + joinPoint.getMethod().getName());
    }

    // 3. @MiniAfterReturning 返回通知 (只有成功返回时执行)
    @MiniAfterReturning("createOrder")
    public void afterReturningCreateOrder(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: AfterReturning method: " + joinPoint.getMethod().getName());
    }

    @MiniAfterReturning("registerUser")
    public void afterReturningRegisterUser(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: AfterReturning method: " + joinPoint.getMethod().getName());
    }

    // 4. @MiniAfterThrowing 异常通知 (只有抛出异常时执行)
    @MiniAfterThrowing("createOrder")
    public void afterThrowingCreateOrder(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: Exception in method: " + joinPoint.getMethod().getName());
        // 实际的异常通知可能需要 Throwable 参数,这里简化为只打印方法名
    }

    @MiniAfterThrowing("registerUser")
    public void afterThrowingRegisterUser(MiniJoinPoint joinPoint) {
        System.out.println("LogAspect: Exception in method: " + joinPoint.getMethod().getName());
    }

    // 5. @MiniAround 环绕通知 (最强大,包裹目标方法执行)
    @MiniAround("createOrder")
    public Object aroundCreateOrder(MiniJoinPoint joinPoint) throws Throwable {
        System.out.println("LogAspect: Around start: " + joinPoint.getMethod().getName());
        Object result = joinPoint.proceed(); // 执行目标方法
        System.out.println("LogAspect: Around end: " + joinPoint.getMethod().getName());
        return result;
    }

    @MiniAround("registerUser")
    public Object aroundRegisterUser(MiniJoinPoint joinPoint) throws Throwable {
        System.out.println("LogAspect: Around start: " + joinPoint.getMethod().getName());
        Object result = joinPoint.proceed(); // 执行目标方法
        System.out.println("LogAspect: Around end: " + joinPoint.getMethod().getName());
        return result;
    }
}
4. 定义切面执行器 MiniAspectExecutor
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package com.yutao.minispring.v7;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class MiniAspectExecutor {
    private Object aspectBean; // 切面实例 (e.g., LogAspect 的实例)
    private List<Method> beforeMethods = new ArrayList<>(); // @MiniBefore 通知方法列表
    private List<Method> afterMethods = new ArrayList<>(); // @MiniAfter 通知方法列表
    private List<Method> afterReturningMethods = new ArrayList<>(); // @MiniAfterReturning 通知方法列表
    private List<Method> afterThrowingMethods = new ArrayList<>(); // @MiniAfterThrowing 通知方法列表
    private Method aroundMethod; // @MiniAround 通知方法
    private String matchMethodName; // 切点方法名匹配 (e.g., "createOrder")

    public MiniAspectExecutor(Object aspectBean, String matchMethodName) {
        this.aspectBean = aspectBean;
        this.matchMethodName = matchMethodName;

        // 收集切面实例中所有带有 AOP 注解的通知方法
        for (Method method : aspectBean.getClass().getDeclaredMethods()) {
            // 确保注解的值与当前切点匹配,这样才能正确收集
            if (method.isAnnotationPresent(MiniBefore.class)
                    && method.getAnnotation(MiniBefore.class).value().equals(matchMethodName)) {
                beforeMethods.add(method);
            }
            if (method.isAnnotationPresent(MiniAfter.class)
                    && method.getAnnotation(MiniAfter.class).value().equals(matchMethodName)) {
                afterMethods.add(method);
            }
            if (method.isAnnotationPresent(MiniAfterReturning.class)
                    && method.getAnnotation(MiniAfterReturning.class).value().equals(matchMethodName)) {
                afterReturningMethods.add(method);
            }
            if (method.isAnnotationPresent(MiniAfterThrowing.class)
                    && method.getAnnotation(MiniAfterThrowing.class).value().equals(matchMethodName)) {
                afterThrowingMethods.add(method);
            }
            if (method.isAnnotationPresent(MiniAround.class)
                    && method.getAnnotation(MiniAround.class).value().equals(matchMethodName)) {
                // 确保环绕通知只有一个
                if (aroundMethod != null) {
                    throw new IllegalStateException("一个切点只能有一个 @MiniAround 通知方法。");
                }
                aroundMethod = method;
            }
        }
    }

    // 提供 getter 供 MiniApplicationContext 使用
    public String getMatchMethodName() {
        return matchMethodName;
    }

    public Object getAspectBean() {
        return aspectBean;
    }

    public List<Method> getBeforeMethods() {
        return beforeMethods;
    }

    public List<Method> getAfterMethods() {
        return afterMethods;
    }

    public List<Method> getAfterReturningMethods() {
        return afterReturningMethods;
    }

    public List<Method> getAfterThrowingMethods() {
        return afterThrowingMethods;
    }

    public Method getAroundMethod() {
        return aroundMethod;
    }

    // 核心方法:执行此切面执行器的通知逻辑
    public Object invoke(MiniJoinPoint joinPoint) throws Throwable {
        Object result = null;
        Throwable caughtException = null;

        try {
            // 1. 如果有环绕通知,则执行环绕通知
            // 环绕通知会调用 joinPoint.proceed() 来继续执行链中的下一个元素(下一个切面执行器或原始目标方法)
            if (aroundMethod != null) {
                // 调用环绕通知方法,它会负责调用 joinPoint.proceed()
                result = aroundMethod.invoke(aspectBean, joinPoint); // 此时,控制流进入 LogAspect.java 中的 aroundCreateOrder 方法:
            } else {
                // 如果没有环绕通知,则依次执行前置、目标方法、后置、返回/异常通知
                // beforeMethods 包含了 LogAspect.beforeCreateOrder 的 Method 对象
                // 2. 执行前置通知
                for (Method before : beforeMethods) {
                    before.invoke(aspectBean, joinPoint); // 这里会通过反射调用 LogAspect.beforeCreateOrder()
                }

                // 3. 继续链中的下一个元素 (可能是下一个 MiniAspectExecutor 或目标方法本身)
                try {
                    result = joinPoint.proceed();
                } catch (java.lang.reflect.InvocationTargetException e) {
                    // 捕获目标方法或后续通知抛出的异常
                    caughtException = e.getTargetException();
                } catch (Throwable e) {
                    caughtException = e;
                }

            }
        } catch (java.lang.reflect.InvocationTargetException e) {
            // 捕获环绕通知本身内部抛出的异常 (如果环绕通知没有处理并重新抛出)
            caughtException = e.getTargetException();
        } catch (Throwable e) {
            caughtException = e;
        } finally {
            // 无论是否有环绕通知,以及是否发生异常,都要执行后置通知
            for (Method after : afterMethods) {
                after.invoke(aspectBean, joinPoint);
            }
        }

        // 只有在发生异常时才执行异常通知
        if (caughtException != null) {
            for (Method throwing : afterThrowingMethods) {
                // 异常通知通常会接收到异常对象,这里简化为只打印
                // 注意:如果 @AfterThrowing 需要异常参数,需要在这里传递
                throwing.invoke(aspectBean, joinPoint);
            }
            throw caughtException; // 重新抛出异常,让调用者感知
        }

        // 只有在没有异常抛出时才执行返回通知
        if (caughtException == null) {
            for (Method afterReturning : afterReturningMethods) {
                // 返回通知可能需要返回值作为参数,这里简化为只传入 joinPoint
                afterReturning.invoke(aspectBean, joinPoint);
            }
        }

        return result;
    }
}
5. 定义代理工厂:带切面处理
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.yutao.minispring.v7;

import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import com.yutao.minispring.v6.MiniMethodInterceptor;

public class MiniProxyFactory {

    // 修复:createProxy 方法现在接收 MiniMethodInterceptor
    // 同时,为了让 MiniMethodInterceptor 能够创建 MiniJoinPoint,需要传入 relevantAspectExecutors
    public static Object createProxy(Object target, MiniMethodInterceptor interceptor) {
        Class<?> targetClass = target.getClass();

        if (targetClass.getInterfaces().length > 0) {
            System.out.println("[MiniProxyFactory] 使用 JDK 动态代理为 " + targetClass.getSimpleName() + " 创建代理。");
            return Proxy.newProxyInstance(
                    targetClass.getClassLoader(),
                    targetClass.getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("[DEBUG-PROXY] JDK InvocationHandler.invoke called for method: "
                                    + method.getName());
                            // 将调用转发给传入的 MiniMethodInterceptor
                            // MiniMethodInterceptor 内部会创建 MiniJoinPoint
                            return interceptor.invoke(method, args, target);
                        }
                    });
        } else {
            System.out.println("[MiniProxyFactory] 使用 CGLIB 动态代理为 " + targetClass.getSimpleName() + " 创建代理。");
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(targetClass);
            enhancer.setCallback(
                    new MethodInterceptor() {
                        @Override
                        public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)
                                throws Throwable {
                            System.out.println("[DEBUG-PROXY] CGLIB MethodInterceptor.intercept called for method: "
                                    + method.getName());
                            // 将调用转发给传入的 MiniMethodInterceptor
                            // MiniMethodInterceptor 内部会创建 MiniJoinPoint
                            // 这里的 target 是原始对象,而不是代理对象 obj
                            return interceptor.invoke(method, args, target);
                        }
                    });
            return enhancer.create();
        }
    }
}
6. 修改容器(MiniApplicationContext)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
package com.yutao.minispring.v7;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yutao.minispring.v3.BeanDefinition;
import com.yutao.minispring.v3.MiniAutowired;
import com.yutao.minispring.v3.MiniInitializingBean;
import com.yutao.minispring.v4.MiniComponent;
import com.yutao.minispring.v5.MiniApplicationEvent;
import com.yutao.minispring.v5.MiniApplicationEventPublisher;
import com.yutao.minispring.v5.MiniApplicationListener;
import com.yutao.minispring.v5.MiniContextRefreshedEvent;
import com.yutao.minispring.v6.MiniMethodInterceptor;

public class MiniApplicationContext implements MiniApplicationEventPublisher {
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private Map<String, Object> singletonMap = new HashMap<>(); // 最终的单例缓存,可能包含代理对象
    private Map<String, Object> singletonObjects = new HashMap<>(); // 用于 refresh 阶段存储原始 Bean
    private List<MiniApplicationListener<?>> applicationListeners = new ArrayList<>();
    // 用于存储解析后的切面执行器
    private List<MiniAspectExecutor> aspectExecutors = new ArrayList<>();

    public void registerBeanDefinition(String name, Class<?> beanClass) {
        BeanDefinition beanDefinition = new BeanDefinition(beanClass);
        beanDefinitionMap.put(name, beanDefinition);
    }

    public MiniApplicationContext(String basePackage) {
        scan(basePackage);
        refresh();
    }

    private void refresh() {
        // 阶段1: 创建所有非懒加载的单例 Bean 的原始实例 (不带 AOP 代理)
        // 这样做是为了确保所有 Bean 都已实例化并可用于依赖注入,包括切面 Bean 自身。
        for (String beanName : beanDefinitionMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if (!beanDefinition.isLazyInit() && "singleton".equals(beanDefinition.getScope())) {
                Object rawInstance = createRawBean(beanName, beanDefinition);
                singletonObjects.put(beanName, rawInstance); // 存储原始 Bean 实例
            }
        }
        // 将原始实例复制到 singletonMap,后续 AOP 代理会替换其中的部分
        singletonMap.putAll(singletonObjects);

        // 阶段2: 初始化切面 (从已创建的原始 Bean 中查找和解析切面)
        initAspect();

        // 阶段3: 对需要 AOP 代理的 Bean 应用代理,并替换 singletonMap 中的原始实例
        // 遍历所有已创建的单例 Bean,判断是否需要代理
        List<String> beanNamesToProcess = new ArrayList<>(singletonMap.keySet()); // 避免并发修改异常
        for (String beanName : beanNamesToProcess) {
            Object currentBean = singletonMap.get(beanName); // 获取当前 Bean (可能是原始的)
            // wrapIfNeeded 会判断是否需要代理,并返回代理对象或原始对象
            Object proxiedInstance = wrapIfNeeded(currentBean);
            if (proxiedInstance != currentBean) { // 如果确实创建了代理
                singletonMap.put(beanName, proxiedInstance); // 用代理对象替换原始对象
            }
        }

        // 收集监听器 (现在从可能已代理的 Bean 中收集)
        for (Object bean : singletonMap.values()) {
            if (bean instanceof MiniApplicationListener) {
                applicationListeners.add((MiniApplicationListener<?>) bean);
            }
        }

        // 发布容器启动完成事件
        publishEvent(new MiniContextRefreshedEvent(this));
    }

    // 辅助方法:创建 Bean 的原始实例,不进行 AOP 代理
    private Object createRawBean(String beanName, BeanDefinition beanDefinition) {
        System.out.println("DEBUG: Entering createRawBean for: " + beanName);
        // 如果是单例且已存在于 singletonObjects 中,直接返回
        if ("singleton".equals(beanDefinition.getScope()) && singletonObjects.containsKey(beanName)) {
            return singletonObjects.get(beanName);
        }

        try {
            Class<?> clazz = beanDefinition.getBeanClass();
            Object instance;

            Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
            Constructor<?> autowiredConstructor = null;

            for (Constructor<?> constructor : declaredConstructors) {
                if (constructor.isAnnotationPresent(MiniAutowired.class)) {
                    autowiredConstructor = constructor;
                    break;
                }
            }

            if (autowiredConstructor != null) {
                Class<?>[] parameterTypes = autowiredConstructor.getParameterTypes();
                Object[] params = new Object[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    // 依赖查找从 singletonObjects 中获取原始 Bean
                    params[i] = findRawBeanByType(parameterTypes[i]); // 使用 findRawBeanByType
                }
                instance = autowiredConstructor.newInstance(params);
            } else {
                instance = clazz.getDeclaredConstructor().newInstance();
            }

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(MiniAutowired.class)) {
                    field.setAccessible(true);
                    Object dependency = findRawBeanByType(field.getType()); // 使用 findRawBeanByType
                    field.set(instance, dependency);
                }
            }

            if (instance instanceof MiniInitializingBean) {
                ((MiniInitializingBean) instance).afterPropertiesSet();
            }

            System.out.println("DEBUG: Exiting createRawBean for: " + beanName);
            return instance;

        } catch (Exception e) {
            throw new RuntimeException("Failed to create raw bean: " + beanName, e);
        }
    }

    // 辅助方法:仅从原始 Bean 缓存中查找 Bean
    private Object findRawBeanByType(Class<?> type) {
        for (Map.Entry<String, Object> entry : singletonObjects.entrySet()) {
            Object beanInstance = entry.getValue();
            if (type.isAssignableFrom(beanInstance.getClass())) {
                return beanInstance;
            }
        }
        // 如果在原始 Bean 缓存中找不到,则抛出异常,表示依赖无法满足
        throw new RuntimeException("Cannot find raw bean of type: " + type.getName() + " for dependency injection.");
    }

    @Override
    public void publishEvent(MiniApplicationEvent event) {
        for (MiniApplicationListener<?> listener : applicationListeners) {
            if (supportsEvent(listener, event)) {
                invokeListener(listener, event);
            }
        }
    }

    private boolean supportsEvent(MiniApplicationListener<?> listener, MiniApplicationEvent event) {
        try {
            java.lang.reflect.Type[] genericInterfaces = listener.getClass().getGenericInterfaces();
            for (java.lang.reflect.Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof java.lang.reflect.ParameterizedType) {
                    java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) genericInterface;
                    if (pt.getRawType().equals(MiniApplicationListener.class)) {
                        java.lang.reflect.Type eventType = pt.getActualTypeArguments()[0];

                        Class<?> eventClass;
                        if (eventType instanceof Class) {
                            eventClass = (Class<?>) eventType;
                        } else if (eventType instanceof java.lang.reflect.WildcardType) {
                            eventClass = (Class<?>) ((java.lang.reflect.WildcardType) eventType).getUpperBounds()[0];
                        } else {
                            return false;
                        }
                        return eventClass.isAssignableFrom(event.getClass());
                    }
                }
            }
        } catch (Exception e) {
            System.err
                    .println("SCAN_ERROR: 处理监听器类型时发生异常: " + listener.getClass().getName() + ", 错误: " + e.getMessage());
            return false;
        }
        return false;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void invokeListener(MiniApplicationListener listener, MiniApplicationEvent event) {
        listener.onApplicationEvent(event);
    }

    public Object getBean(String name) {
        BeanDefinition definition = beanDefinitionMap.get(name);
        if (definition == null) {
            throw new RuntimeException("No bean named " + name);
        }
        if ("singleton".equals(definition.getScope())) {
            Object bean = singletonMap.get(name);
            // 如果是懒加载单例,在这里创建并代理
            if (bean == null) {
                bean = createBean(name, definition); // createBean 会处理代理
            }
            return bean;
        } else {
            return createBean(name, definition); // 原型 Bean 每次都创建并代理
        }
    }

    /**
     * 扫描指定包路径下的类,查找并注册带有 @MiniComponent 注解的 Bean 定义。
     * 目前仅扫描指定包的直接子级,不进行递归扫描子包。
     *
     * @param basePackage 要扫描的基础包名,例如 "com.yutao.minispring.v6"
     */
    private void scan(String basePackage) {
        System.out.println("SCAN_DEBUG: 开始扫描基础包: " + basePackage);
        String path = basePackage.replace('.', '/');
        System.out.println("SCAN_DEBUG: 转换后的包路径: " + path);
        // Java 的原则是:每个线程都有一个与之关联的“上下文类加载器”(Context ClassLoader)
        // 这不意味着每个线程都拥有一个自己独有的类加载器实例
        // 而是说每个线程都可以设置或获取一个默认的类加载器,供该线程中运行的代码(尤其是框架和库代码)使用,以便在运行时加载类和资源
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL resource = classLoader.getResource(path);
        if (resource == null) {
            System.err.println("SCAN_ERROR: 未找到基础包资源: " + basePackage + "。这很可能是导致问题的原因!");
            throw new RuntimeException("未找到包资源: " + basePackage);
        }
        System.out.println("SCAN_DEBUG: 找到的资源URL: " + resource.toString());
        File baseDir = null;
        try {
            baseDir = new File(resource.toURI());
        } catch (Exception e) {
            System.err.println("SCAN_ERROR: 无法将资源URL转换为文件URI: " + resource.toString() + "。错误: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("无法获取包的基础目录: " + basePackage, e);
        }
        System.out.println("SCAN_DEBUG: 扫描基础目录: " + baseDir.getAbsolutePath());
        if (!baseDir.exists() || !baseDir.isDirectory()) {
            System.err.println("SCAN_ERROR: 基础目录不存在或不是一个目录: " + baseDir.getAbsolutePath() + "。这是一个严重的扫描问题。");
            throw new RuntimeException("扫描基础目录无效: " + baseDir.getAbsolutePath());
        }
        File[] files = baseDir.listFiles();
        if (files == null) {
            System.err.println("SCAN_ERROR: 无法列出目录文件: " + baseDir.getAbsolutePath() + "。目录可能无法访问或不是实际目录(例如在 JAR 包内部)。");
            throw new RuntimeException("无法列出目录文件: " + baseDir.getAbsolutePath());
        }
        System.out.println("SCAN_DEBUG: 找到的文件/目录数量: " + files.length);
        for (File file : files) {
            System.out.println("SCAN_DEBUG: 正在处理文件/目录: " + file.getName());
            if (file.isDirectory()) {
                System.out.println("SCAN_DEBUG: 跳过子目录(当前未实现递归扫描): " + file.getName());
                continue;
            }
            if (file.getName().endsWith(".class")) {
                String className = basePackage + '.' + file.getName().replace(".class", "");
                System.out.println("SCAN_DEBUG: 尝试加载类: " + className);
                try {
                    Class<?> clazz = Class.forName(className);
                    System.out.println("SCAN_DEBUG: 成功加载类: " + clazz.getName());
                    if (clazz.isAnnotationPresent(MiniComponent.class)) {
                        String beanName = Introspector.decapitalize(clazz.getSimpleName());
                        System.out.println("SCAN_DEBUG: 发现带有 @MiniComponent 注解的类: " + clazz.getName()
                                + ",计算出的 Bean 名称: " + beanName);
                        registerBeanDefinition(beanName, clazz);
                    } else {
                        System.out.println("SCAN_DEBUG: 类 " + clazz.getName() + " 未找到 @MiniComponent 注解。");
                    }
                } catch (ClassNotFoundException e) {
                    System.err.println("SCAN_ERROR: 扫描时未找到类: " + className + "。错误: " + e.getMessage());
                } catch (Exception e) {
                    System.err.println("SCAN_ERROR: 处理类 " + className + " 时发生意外错误: " + e.getMessage());
                    e.printStackTrace();
                }
            } else {
                System.out.println("SCAN_DEBUG: 跳过非 .class 文件: " + file.getName());
            }
        }
        System.out.println("SCAN_DEBUG: 基础包扫描完成: " + basePackage);
        System.out.println("SCAN_DEBUG: 扫描后 beanDefinitionMap 大小: " + beanDefinitionMap.size());
        beanDefinitionMap.keySet().forEach(name -> System.out.println("SCAN_DEBUG: 已注册的 Bean: " + name));
    }

    // createBean 方法现在主要用于懒加载或原型 Bean 的创建,以及 refresh 阶段的第二遍处理
    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        System.out.println("DEBUG: Entering createBean for: " + beanName);
        // 如果是单例且已在 singletonMap 中(在 refresh 阶段创建的原始 Bean 或已代理的 Bean),直接返回
        if ("singleton".equals(beanDefinition.getScope()) && singletonMap.containsKey(beanName)) {
            return singletonMap.get(beanName);
        }

        try {
            Class<?> clazz = beanDefinition.getBeanClass();
            Object instance;

            Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
            Constructor<?> autowiredConstructor = null;

            for (Constructor<?> constructor : declaredConstructors) {
                if (constructor.isAnnotationPresent(MiniAutowired.class)) {
                    autowiredConstructor = constructor;
                    break;
                }
            }

            if (autowiredConstructor != null) {
                Class<?>[] parameterTypes = autowiredConstructor.getParameterTypes();
                Object[] params = new Object[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    params[i] = getBean(Introspector.decapitalize(parameterTypes[i].getSimpleName())); // 递归调用 getBean
                                                                                                       // 获取依赖
                                                                                                       // (可能获取到代理对象)
                }
                instance = autowiredConstructor.newInstance(params);
            } else {
                instance = clazz.getDeclaredConstructor().newInstance();
            }

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(MiniAutowired.class)) {
                    field.setAccessible(true);
                    Object dependency = getBean(Introspector.decapitalize(field.getType().getSimpleName())); // 递归调用
                                                                                                             // getBean
                                                                                                             // 获取依赖
                    field.set(instance, dependency);
                }
            }

            if (instance instanceof MiniInitializingBean) {
                ((MiniInitializingBean) instance).afterPropertiesSet();
            }

            // 检查并应用 AOP 代理
            Object proxiedInstance = wrapIfNeeded(instance);

            // 如果是单例且尚未缓存,则将其放入 singletonMap
            if ("singleton".equals(beanDefinition.getScope()) && !singletonMap.containsKey(beanName)) {
                singletonMap.put(beanName, proxiedInstance);
            }

            System.out.println("DEBUG: Exiting createBean for: " + beanName);
            return proxiedInstance;

        } catch (Exception e) {
            throw new RuntimeException("Failed to create bean: " + beanName, e);
        }
    }

    // 负责判断 Bean 是否需要 AOP 代理,并创建代理
    private Object wrapIfNeeded(Object bean) {
        // 切面 Bean 本身通常不应该被代理,避免自引用和无限循环
        if (bean.getClass().isAnnotationPresent(MiniAspect.class)) {
            System.out
                    .println("DEBUG: wrapIfNeeded Skipping proxy for aspect bean: " + bean.getClass().getSimpleName());
            return bean;
        }

        // 检查该 Bean 的任何方法是否匹配任何已定义的切点
        boolean needsProxy = false;
        List<MiniAspectExecutor> relevantAspectExecutors = new ArrayList<>();

        for (MiniAspectExecutor ae : aspectExecutors) {
            for (Method beanMethod : bean.getClass().getMethods()) {
                if (beanMethod.getName().equals(ae.getMatchMethodName())) {
                    needsProxy = true;
                    if (!relevantAspectExecutors.contains(ae)) {
                        relevantAspectExecutors.add(ae);
                    }
                }
            }
        }

        if (needsProxy) {
            System.out.println("DEBUG: wrapIfNeeded 发现匹配的切点,尝试创建代理 for: " + bean.getClass().getSimpleName());
            // 创建一个 MiniMethodInterceptor,它将协调所有匹配的通知
            // FIX: 移除 MiniMethodInterceptor 中直接处理 Around 以及其他通知的逻辑
            // 它的职责是创建 MiniJoinPoint 并调用 proceed 来启动整个通知链
            return MiniProxyFactory.createProxy(bean, new MiniMethodInterceptor() {
                @Override
                public Object invoke(Method method, Object[] args, Object target) throws Throwable {
                    // 只收集当前被调用的方法所匹配的切面执行器
                    List<MiniAspectExecutor> currentMethodMatchingAspectExecutors = new ArrayList<>();
                    for (MiniAspectExecutor ae : relevantAspectExecutors) {
                        if (method.getName().equals(ae.getMatchMethodName())) {
                            currentMethodMatchingAspectExecutors.add(ae);
                        }
                    }

                    // 创建 MiniJoinPoint,并将当前方法匹配到的所有切面执行器传递给它
                    // MiniJoinPoint 负责维护执行链的顺序和调用 proceed()
                    MiniJoinPoint joinPoint = new MiniJoinPoint(method, args, target,
                            currentMethodMatchingAspectExecutors);

                    // 核心改变:直接调用 MiniJoinPoint 的 proceed() 方法
                    // MiniJoinPoint 将负责遍历并执行所有匹配的 MiniAspectExecutor 及其内部的通知
                    return joinPoint.proceed();
                }
            });
        }
        System.out.println("DEBUG: wrapIfNeeded 未发现匹配的切点,返回原始 Bean: " + bean.getClass().getSimpleName());
        return bean;
    }

    // 初始化切面:在所有单例 Bean 创建完成后调用
    private void initAspect() {
        System.out.println("DEBUG: initAspect 开始初始化切面。");
        // 遍历所有已创建的单例 Bean,查找切面
        for (Object bean : singletonObjects.values()) { // FIX: 使用 singletonObjects
            Class<?> clazz = bean.getClass();
            // 检查 Bean 是否是 @MiniAspect 注解的切面类
            if (clazz.isAnnotationPresent(MiniAspect.class)) {
                System.out.println("DEBUG: 发现切面类: " + clazz.getSimpleName());
                // 遍历切面类中的所有方法,查找 @MiniPointcut 注解
                for (Method method : clazz.getDeclaredMethods()) {
                    if (method.isAnnotationPresent(MiniPointcut.class)) {
                        MiniPointcut pointcut = method.getAnnotation(MiniPointcut.class);
                        String matchMethodName = pointcut.value(); // 获取切点值 (匹配的方法名)
                        System.out.println(
                                "DEBUG: Found pointcut '" + matchMethodName + "' in aspect " + clazz.getSimpleName());
                        // 为每个切面和切点创建一个 MiniAspectExecutor
                        aspectExecutors.add(new MiniAspectExecutor(bean, matchMethodName));
                    }
                }
            }
        }
        System.out.println(
                "DEBUG: Aspect initialization complete. Found " + aspectExecutors.size() + " aspect executors.");
    }
}

然后在 createBean() 的 wrapIfNeeded()中统一代理:

1
2
3
4
5
6
private Object wrapIfNeeded(Object bean) {
    for (MiniAspectExecutor aspectExecutor : aspectExecutors) {
        return MiniProxyFactory.createProxy(bean, aspectExecutor);
    }
    return bean;
}
7. 定义业务类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * 订单服务接口,用于演示JDK动态代理。
 * JDK动态代理要求目标类实现接口。
 */
public interface IOrderService {
    void createOrder();
}


/**
 * 订单服务实现类,作为AOP的目标Bean。
 * 被@MiniComponent注解,以便MiniApplicationContext扫描和管理。
 * 实现IOrderService接口,以便测试JDK动态代理。
 */
@MiniComponent
public class OrderService implements IOrderService {
    @Override
    public void createOrder() {
        System.out.println("OrderService: 创建订单...");
        // 取消注释可以测试异常通知
        // throw new RuntimeException("模拟订单创建异常");
    }
}

/**
 * 用户服务类,作为AOP的目标Bean。
 * 被@MiniComponent注解,以便MiniApplicationContext扫描和管理。
 * 不实现任何接口,以便测试CGLIB动态代理。
 */
@MiniComponent
public class UserService {
    public void registerUser() {
        System.out.println("UserService: 注册用户...");
        // 取消注释可以测试异常通知
        // throw new RuntimeException("模拟用户注册异常");
    }
}
8. 测试启动
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.yutao.minispring.v7;

public class TestAop {
    public static void main(String[] args) {
        System.out.println("DEBUG: 启动 MiniApplicationContext...");
        // 传入包含所有业务Bean和切面Bean的包路径
        MiniApplicationContext context = new MiniApplicationContext("com.yutao.minispring.v7");

        System.out.println("\n--- 测试 OrderService (createOrder) - 正常执行 ---");
        // 获取OrderService的Bean,它应该是一个JDK代理对象
        IOrderService orderService = (IOrderService) context.getBean("orderService");
        System.out.println("DEBUG: orderService 实际运行时类: " + orderService.getClass().getName());
        orderService.createOrder();

        System.out.println("\n--- 测试 UserService (registerUser) - 正常执行 ---");
        // 获取UserService的Bean,它应该是一个CGLIB代理对象
        UserService userService = (UserService) context.getBean("userService");
        System.out.println("DEBUG: userService 实际运行时类: " + userService.getClass().getName());
        userService.registerUser();

        System.out.println("\n--- 测试 OrderService (createOrder) - 模拟异常 ---");
        try {
            // 再次获取OrderService的Bean,并模拟抛出异常
            // 请在OrderService.java中取消相关注释以测试异常
            IOrderService orderServiceWithException = (IOrderService) context.getBean("orderService");
            System.out.println(
                    "DEBUG: orderServiceWithException 实际运行时类: " + orderServiceWithException.getClass().getName());
            orderServiceWithException.createOrder();
        } catch (Exception e) {
            System.out.println("DEBUG: 捕获到预期异常: " + e.getMessage());
        }

        System.out.println("\n--- 测试 UserService (registerUser) - 模拟异常 ---");
        try {
            // 再次获取UserService的Bean,并模拟抛出异常
            // 请在UserService.java中取消相关注释以测试异常
            UserService userServiceWithException = (UserService) context.getBean("userService");
            System.out.println(
                    "DEBUG: userServiceWithException 实际运行时类: " + userServiceWithException.getClass().getName());
            userServiceWithException.registerUser();
        } catch (Exception e) {
            System.out.println("DEBUG: 捕获到预期异常: " + e.getMessage());
        }
    }
}

最终体系一览(完整版)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
+-------------------------------------+
| MiniApplicationContext              |
|  - initAspect()                     |
|  - createBean()                     |
|  - wrapIfNeeded()                   |
+---------------------+---------------+
                      |
                      v
        +---------------------------+
        | MiniAspectExecutor         |
        |  - beforeMethods           |
        |  - afterMethods            |
        |  - throwingMethods         |
        |  - aroundMethod            |
        +---------------------------+
                      |
                      v
+------------------------+        +--------------------+
| MiniProxyFactory        |-----> | JDK Proxy / CGLIB    |
|  - createProxy()        |        +--------------------+
|  - apply aspectExecutor |
+------------------------+

AOP调用链时序图

sequenceDiagram
    participant User
    participant Proxy as OrderService Proxy
    participant Interceptor as MiniMethodInterceptor
    participant JoinPoint as MiniJoinPoint
    participant LogExecutor as LogAspectExecutorForCreateOrder
    participant LogAspect as LogAspect Instance
    participant SecurityExecutor as SecurityAspectExecutorForCreateOrder
    participant SecurityAspect as SecurityAspect Instance
    participant Target as OrderService Target

    User->>Proxy: 调用 createOrder("user", "item")
    activate Proxy
    Proxy->>Interceptor: invoke(method, args, target)
    activate Interceptor
    Interceptor->>JoinPoint: 创建初始 MiniJoinPoint (jp0, index=-1)
    Interceptor->>JoinPoint: jp0.proceed()
    
    JoinPoint->>LogExecutor: invoke(jp1) (jp1, index=0)
    activate LogExecutor
    Note over LogExecutor: 根据 MiniAspectExecutor 逻辑:<br>因有 @Around,@Before 不在此处执行
    LogExecutor->>LogAspect: 调用 aroundCreateOrder(jp1) (通过反射)
    activate LogAspect
    LogAspect->>JoinPoint: jp1.proceed()
    
    JoinPoint->>SecurityExecutor: invoke(jp2) (jp2, index=1)
    activate SecurityExecutor
    Note over SecurityExecutor: 根据 MiniAspectExecutor 逻辑:<br>因有 @Around,@Before 不在此处执行
    SecurityExecutor->>SecurityAspect: 调用 securityAroundCreateOrder(jp2) (通过反射)
    activate SecurityAspect
    SecurityAspect->>JoinPoint: jp2.proceed()
    
    JoinPoint->>Target: 调用 createOrder(user, item) (没有更多拦截器)
    activate Target
    Target-->>SecurityAspect: 返回结果 (e.g., "ORD123")
    deactivate Target
    
    SecurityAspect-->>SecurityExecutor: 返回结果 (来自 aroundCreateOrder)
    deactivate SecurityAspect
    SecurityExecutor->>SecurityExecutor: 执行 @After / @AfterReturning 通知
    SecurityExecutor-->>LogAspect: 返回结果
    deactivate SecurityExecutor
    
    LogAspect-->>LogExecutor: 返回结果 (来自 aroundCreateOrder)
    deactivate LogAspect
    LogExecutor->>LogExecutor: 执行 @After / @AfterReturning 通知
    LogExecutor-->>Interceptor: 返回结果
    deactivate LogExecutor
    
    Interceptor-->>Proxy: 返回结果
    deactivate Interceptor
    Proxy-->>User: 返回结果
    deactivate Proxy

MiniSpring 整体逻辑调用图

flowchart TD
    subgraph 容器初始化阶段
        A[Application Startup] --> B{Context Refresh}
        B --> C[Scan Bean Definitions]
        C -- Fill beanDefinitionMap --> D[Create and Register Singleton Beans]
        D -- Fill singletonObjects --> E[Initialize Aspects]
    end

    subgraph 切面初始化
        E --> E1{Iterate Singleton Objects}
        E1 -- Find @MiniAspect Bean --> E2[Parse @MiniPointcut]
        E2 -- For each Matching Pointcut --> E3[Create MiniAspectExecutor Instance]
        E3 -- Fill AspectExecutors List --> F[AOP Proxy Creation]
    end

    subgraph AOP代理创建
        F --> F1{Is Current Bean @MiniAspect?}
        F1 -- Yes --> F2[Return Original Bean]
        F1 -- No --> F3{Does the Bean's Method Match Any Pointcut?}
        F3 -- No --> F2
        F3 -- Yes --> F4[Create MiniProxyFactory Create Proxy]
        F4 -- Pass Original Bean and MiniMethodInterceptor --> G[Proxy Object Replaces Original Bean in Singleton Map]
    end

    subgraph 用户代码调用代理方法
        H[User Code Call] --> I{Proxy Interception}
    end

    subgraph MiniMethodInterceptor类Invoke方法内部流程
        I --> I1[Filter Current Method Matching Aspect Executors]
        I1 --> I2[Create MiniJoinPoint]
        I2 --> J[First Call]
    end

    subgraph MiniJoinPoint类的Proceed方法AOP责任链
        J --> K{Current Index < Total Number of Interceptors - 1?}
        K -- Yes --> L[Create Next JoinPoint]
        L --> M[Get Next Executor]
        M --> N[Call Next Executor Invoke]
        N -- Next Executor Invoke --> J

        K -- No --> P[Execute Original Target Method]
    end

    subgraph MiniAspectExecutor类Invoke方法通知执行
        N --> N1[Execute @MiniBefore Notification]
        N1 --> N2{Is there @MiniAround Notification?}
        N2 -- Yes --> N3[Call Around Method]
        N3 -- Inside Around Method Call --> J
        N2 -- No --> J
        N3 --> N4[Execute @MiniAfter Notification]
        N4 --> N5[Handle Exception & Execute @MiniAfterThrowing Notification]
        N5 --> N6[Execute @MiniAfterReturning Notification]
        N6 --> Q[Return Result to Upper Caller]
    end

    subgraph 结果返回
        P --> Q
        Q -- Return to Previous MiniAspectExecutor Invoke --> N
        N -- Ultimately Return to MiniMethodInterceptor Invoke --> I
        I --> R[Return Result to User Code]
    end

总结

Spring 框架是 Java 生态的基石,必知必会。