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
相关推荐
风象南9 分钟前
Claude Code这个隐藏技能,让我告别PPT焦虑
人工智能·后端
神奇小汤圆39 分钟前
为什么 Spring 强烈推荐你用 singleton
后端
Java编程爱好者40 分钟前
面试必问:Semaphore 凭什么靠 AQS + CAS 实现限流?
后端
Java编程爱好者1 小时前
十万个why:加了 LIMIT 1,为什么查询反而变慢了?
后端
JavaTalks2 小时前
高并发保护实战:限流、熔断、降级如何配合落地
后端·架构·设计
代码丰2 小时前
为什么Java 接口中的存在 Static 和 Default 方法?
后端
用户571155176832 小时前
深入解析Spring BeanPostProcessor
后端
掘金者阿豪4 小时前
🚀 CentOS Stream 9服务器Docker部署KWDB:从零到跨模查询实战全记录
后端
yang_xin_yu4 小时前
一文带你精通泛型PECS原则与四大核心函数式接口
后端