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
相关推荐
小信丶1 小时前
@EnableTransactionManagement注解介绍、应用场景和示例代码
java·spring boot·后端
To Be Clean Coder1 小时前
【Spring源码】createBean如何寻找构造器(四)——类型转换与匹配权重
java·后端·spring
-孤存-1 小时前
SpringBoot核心注解与配置详解
java·spring boot·后端
2301_818732062 小时前
项目启动报错,错误指向xml 已解决
xml·java·数据库·后端·springboot
小王不爱笑1323 小时前
SpringBoot 整合 Ollama + 本地 DeepSeek 模型
java·spring boot·后端
短剑重铸之日4 小时前
《设计模式》第七篇:适配器模式
java·后端·设计模式·适配器模式
树码小子6 小时前
SpringIoC & DI (1):IOC介绍 & Spring IoC使用 & DI
java·后端·spring
墨染青竹梦悠然7 小时前
基于Django+vue的图书借阅管理系统
前端·vue.js·后端·python·django·毕业设计·毕设
怪兽毕设7 小时前
基于Django的洗衣服务平台设计与实现
后端·python·django·洗衣服务平台
程序员泠零澪回家种桔子7 小时前
微服务日志治理:ELK 栈实战指南
后端·elk·微服务·云原生·架构