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
相关推荐
Java爱好狂.6 分钟前
复杂知识简单学!Springboot加载配置文件源码分析
java·spring boot·后端·spring·java面试·后端开发·java程序员
小贝IT~40 分钟前
基于SpringBoot的图书个性化推荐系统-048
java·spring boot·后端
断春风1 小时前
SpringBoot 集成 XXL-JOB
java·spring boot·后端
橘子海全栈攻城狮1 小时前
【最新源码】基于springboot的会议室预订系统设计与实现 014
java·开发语言·前端·spring boot·后端·spring·自动化
9号达人2 小时前
Jackson序列化让验签失败?破解JSON转义陷阱
java·后端·面试
LambHappiness2 小时前
Grafana LDAP配置故障排查:从3小时到10分钟的AI辅助解决方案
后端
她说..2 小时前
Spring AOP场景3——接口防抖(附带源码)
java·后端·spring·java-ee·springboot
海上彼尚2 小时前
Go之路 - 7.go的函数
开发语言·后端·golang
martinzh3 小时前
NL2SQL解决了?别闹了!大模型让你和数据库聊天背后的真相
后端