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
相关推荐
欲买桂花同载酒11 分钟前
postgis空间坐标系实践
后端
码事漫谈12 分钟前
智能运维与资源优化:金仓数据库助力企业年省百万运维成本
后端
苏三说技术25 分钟前
5种分布式配置中心
后端
武子康29 分钟前
大数据-148 Flink 写入 Kudu 实战:自定义 Sink 全流程(Flink 1.11/Kudu 1.17/Java 11)
大数据·后端·nosql
星释34 分钟前
Rust 练习册 :Macros与宏系统
开发语言·后端·rust
林太白1 小时前
rust18-通知管理模块
后端·rust
一 乐1 小时前
医疗管理|医院医疗管理系统|基于springboot+vue医疗管理系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·医疗管理系统
华仔啊2 小时前
SpringBoot 2.x 和 3.x 的核心区别,这些变化你必须知道
java·spring boot·后端
程序员爱钓鱼2 小时前
Python编程实战——Python实用工具与库:Matplotlib数据可视化
前端·后端·python