Spring学习笔记

IOC

spring的bean创建过程(粗略的)

  1. 读取配置
  2. 将各种bean的定义封装为BeanDefinition,存入到beanDefinitionMap中
  3. 调用BeanFactoryPostProcessorpostProcessBeanFactory方法(可以自己实现BeanFactoryPostProcessor,做到例如修改某个BeanDefinition、自己往beanDefinitionMap注册额外的BeanDefinition等事情)
  4. 遍历beanDefinitionMap,根据beanDefinition通过反射创建实例
  5. 给每个bean填充属性
  6. 调用BeanPostProcessorpostProcessBeforeInitialization方法
  7. 调用InitialingBeanafterPropertiesSet方法
  8. 调用BeanPostProcessorpostProcessAfterInitialization方法

Bean工厂后处理器(BeanFactoryPostProcessor)

示例(自己注册BeanDefinition)

java 复制代码
@SpringBootApplication
public class SpringDemoApplication {
  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);
    // 容器启动后该方法会被调用,即使MyTestBean并没有加@Component注解被扫描为bean
    context.getBean("myTestBean", MyTestBean.class).test();
  }
}
java 复制代码
public class MyTestBean {
  public void test() {
    System.out.println("================ MyTestBean test method called");
  }
}
java 复制代码
@Component
public class MyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {
  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    System.out.println("================ postProcessBeanDefinitionRegistry called");
    BeanDefinition bdf = new GenericBeanDefinition();
    bdf.setBeanClassName("com.example.demo.ioc.MyTestBean");
    registry.registerBeanDefinition("myTestBean", bdf);
  }
}

Bean后处理器(BeanPostProcessor)

java 复制代码
@SpringBootApplication
public class SpringDemoApplication {
  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);;
    context.getBean(MyTestBean.class).test();
  }
}
java 复制代码
public class MyTestBean {
  public void test() {
    System.out.println("================ MyTestBean test method called");
  }
}
java 复制代码
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof MyTestBean) {
      System.out.println("================ bean后处理器的before方法执行: MyTestBean");
    }
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof MyTestBean) {
      System.out.println("================ bean后处理器的after方法执行: MyTestBean");
    }
    return bean;
  }
}

容器启动后打印结果:

ini 复制代码
================ bean后处理器的before方法执行: MyTestBean
================ bean后处理器的after方法执行: MyTestBean
================ MyTestBean test method called

InitializingBean

实现了InitializingBean接口的bean在填充完属性之后它的afterPropertiesSet方法会被自动调用(在BeanPostProcessorbefore方法之后,after方法之前),没什么好说的

java 复制代码
@Component
public class MyTestBean implements InitializingBean {
  public void test() {
    System.out.println("================ MyTestBean test method called");
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    System.out.println("================ MyTestBean afterPropertiesSet method called");
  }
}

容器启动后打印结果:

ini 复制代码
================ bean后处理器的before方法执行: MyTestBean
================ MyTestBean afterPropertiesSet method called
================ bean后处理器的after方法执行: MyTestBean
================ MyTestBean test method called

AOP

基础示例

启动类

java 复制代码
@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringDemoApplication {
  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);;
    context.getBean(MyAopTestBean.class).test("spring aop");
  }
}

测试bean

java 复制代码
@Component
public class MyAopTestBean {
  public void test(String name) {
    System.out.println("hi " + name);
  }
}

切面配置

java 复制代码
@Aspect
@Component
public class MyAspect {
  @Before("execution(* com.example.demo.aop.MyAopTestBean.*(..))")
  public void before() {
    System.out.println("======== 前置通知执行");
  }

  @Around("execution(* com.example.spring_demo.aop.MyAopTestBean.*(..))")
  public void around(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("======== 环绕通知 - before 参数:" + Arrays.toString(joinPoint.getArgs()));
    joinPoint.proceed(joinPoint.getArgs());
    System.out.println("======== 环绕通知 - after");
  }
}

容器启动后打印结果:

diff 复制代码
======== 环绕通知 - before 参数:[spring aop]
======== 前置通知执行
hi spring aop
======== 环绕通知 - after
相关推荐
逝水无殇19 分钟前
C# 异常处理详解
开发语言·后端·c#
考虑考虑3 小时前
Sentinel安装
java·后端·微服务
IT_陈寒3 小时前
SpringBoot自动配置失灵?你可能忘了这个关键注解
前端·人工智能·后端
碎碎念_4923 小时前
SpringBoot + Vue 前后端分离从 0 到 1 完整环境配置流程
vue.js·spring boot·后端
逝水无殇3 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
YIAN3 小时前
从手写 Agent 工具到 MCP 协议:一文搞懂大模型跨进程跨语言工具调用
后端·agent·mcp
小兔崽子去哪了4 小时前
Docker 删除镜像后磁盘空间没有释放?
后端·docker·容器
高明珠4 小时前
麒麟 V10 SP1 排查实录:ttyS5 每 10 秒莫名收到一批报文,元凶是 eGTouchD
后端
卷无止境4 小时前
Python FFI 技术深度解析:ctypes、cffi 与 pybind11 的性能差异与实践挑战
后端·python
ServBay5 小时前
AI Gateway 是什么?为什么每个平台都在做
后端·aigc·ai编程