当前位置: 首页 > news >正文

Spring的Bean的生命周期与自动注入细节

1. Bean的生命周期

通过一个LifeCycleBean和一个MyBeanPostProcessor来观察Bean的生命周期:

构造(实例化)->依赖注入(前后处理)->初始化(前后处理)->销毁

LifeCycleBean

@Component
public class LifeCycleBean {private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);//1.最先执行public LifeCycleBean(){log.info("构造");}//2.依赖注入@Autowired
//    public void autowire(@Value("${JAVA_HOME}")String home){ 这种方式好像要较新版本Spring才行
//        log.debug("依赖注入:{}", home);
//    }public void autowire(Bean1 bean1){log.info("依赖注入:{}", bean1);}//3.初始化@PostConstructpublic void init(){log.info("初始化");}//4.销毁方法(仅在单例的时候调用, 其他scope调用时机不一样)@PreDestroypublic void destroy(){log.info("销毁");}}

MyBeanPostProcessor, 实现了InstantiationAwareBeanPostProcessor

@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);// 实例化之前@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")) {log.info("初始化之前执行, 这里返回的bean会替换原版本的bean");}return null;}// 实例化之后@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")) {log.info("实例化之后执行, 这里返回false会跳过依赖注入阶段");//return false;}return true;}// 依赖注入阶段执行@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if(beanName.equals("lifeCycleBean")){log.info("依赖注入阶段执行, 如@Autowired, @Value, @Resource");}return pvs;}// 初始化之前@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if(beanName.equals("lifeCycleBean")){log.info("初始化之前执行, 这里返回的对象会替换原本的bean, 如@PostConstruct, @ConfigurationProperties");}return bean;}// 初始化之后执行@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")) {log.info("初始化之后执行, 这里返回的对象会替换原本的bean, 如代理增强");}return bean;}// 销毁之前@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {if(beanName.equals("lifeCycleBean")){log.info("销毁之前执行, 如 @PreDestroy");}}}

运行结果:

[main]: 初始化之前执行, 这里返回的bean会替换原版本的bean --- postProcessBeforeInstantiation
[main]: 构造
[main]: 实例化之后执行, 这里返回false会跳过依赖注入阶段 --- postProcessAfterInstantiation
[main]: 依赖注入阶段执行,@Autowired, @Value, @Resource --- postProcessProperties
[main]: 依赖注入:com.yadong.springsourcestudy.chapter2.Bean1@21c64522
[main]: 初始化之前执行, 这里返回的对象会替换原本的bean,@PostConstruct, @ConfigurationProperties --- postProcessBeforeInitialization
[main]: 初始化
[main]: 初始化之后执行, 这里返回的对象会替换原本的bean, 如代理增强 --- postProcessAfterInitialization
[main]: 销毁之前执行,@PreDestroy --- postProcessBeforeDestruction
[main]: 销毁

2. @Autowired依赖注入的处理细节

依赖注入依靠AutowiredAnnotationBeanPostProcessor通过容器调用processor.postProcessProperties()执行依赖注入,

其过程是postProcessProperties()->InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs)

->metadata.inject(bean, beanName, pvs);

这个过程找了需要@Autowired的字段或方法后, 需要一些解析器来解析, 如 ContextAnnotationAutowireCandidateResolver, StandardEnvironment()::resolvePlaceholders

以下是一个手动调用解析@Autowired的过程:

public class AutowiredAnnotationBPP {public static void main(String[] args) throws Throwable {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //解析@ValuebeanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);   //解析${}beanFactory.registerSingleton("bean2", new Bean2());beanFactory.registerSingleton("bean3", new Bean3());//1. 查找有哪些属性方法加了@Autowire, 这称之为InjectionMetadataAutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();processor.setBeanFactory(beanFactory);Bean1 bean1 = new Bean1();Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);findAutowiringMetadata.setAccessible(true);InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);System.out.println("metadata = " + metadata);//2. metadata中存储了该bean要autowire的字段,方法等信息, 调用inject完成依赖注入metadata.inject(bean1, "bean1", null);System.out.println(bean1);//以下是要查找注入对象的过程Field bean2 = Bean1.class.getDeclaredField("bean2");DependencyDescriptor dd1 = new DependencyDescriptor(bean2, false);Object o = beanFactory.doResolveDependency(dd1, null, null, null);System.out.println(o);Method setBean2 = Bean1.class.getDeclaredMethod("setBean3", Bean3.class);DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);Object o1 = beanFactory.doResolveDependency(dd2, null, null, null);System.out.println(o1);}
}//Bean1.java
@Component
public class Bean1 {@AutowiredBean2 bean2;Bean3 bean3;@Autowiredpublic void setBean3(Bean3 bean3){this.bean3 = bean3;}
}

3. 常见后置处理器

  1. ConfigurationClassPostProcessor 能解析@ComponentScan, @Bean, @Import, @ImportResource

  2. MapperScannerConfigurer 解析@MapperScanner, SSM中用, SpringBoot已经实现了自动装配因此用不上

  3. AutowiredAnnotationBeanPostProcessor 解析@Autowire

4. 自实现ComponentScanPostProcessor

public class Chapter4Application {public static void main(String[] args) throws IOException {// 干净的容器GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config", Config.class);// 自己实现的, 解析@ComponentScancontext.registerBean(ComponentScanPostProcessor.class);context.refresh();for (String beanDefinitionName : context.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}context.close();}
}// 自己实现的ComponentScanPostProcessor
public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {// 在 context.refresh()时, 读取bd后, 实例化bean前, 会调用这个方法@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {try{ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);if(componentScan != null){for (String p : componentScan.basePackages()) {System.out.println(p);// com.yadong.springsourcestudy.chapter4 -> classpath*:com/yadong/springsourcestudy/chapter4/**/*.classString path = "classpath:*" + p.replace(".", "/") + "/**/*.class";CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();  //读取资源的元信息System.out.println(path);Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();for (Resource resource : resources) {System.out.println(resource);MetadataReader metadataReader = factory.getMetadataReader(resource);ClassMetadata classMetadata = metadataReader.getClassMetadata();System.out.println("类名:" + classMetadata.getClassName());//hasMetaAnnotation间接继承的注解也会扫描到System.out.println("是否加了 @Component " + metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));if(metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName())|| metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())){AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();DefaultListableBeanFactory beanFactory = null;if (configurableListableBeanFactory instanceof DefaultListableBeanFactory) {beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;}String bdn = generator.generateBeanName(bd, beanFactory);beanFactory.registerBeanDefinition(bdn, bd);}}}}}catch (Exception e){e.printStackTrace();}}
}
http://www.lryc.cn/news/7483.html

相关文章:

  • 谷粒商城:订单中心概念解析
  • 快递员配送手机卡,要求当面激活有“猫腻”吗?
  • Sage X3 ERP的称重插件帮助食品和化工企业实现精细化管理
  • 【笔试强训】Day_01
  • 字节跳动青训营--前端day9
  • 如何把模糊的照片还原?
  • 29-Golang中的切片
  • 闲聊一下开源
  • 用这4招优雅的实现Spring Boot 异步线程间数据传递
  • RocketMQ源码分析之NameServer
  • 如何优化认知配比
  • WuThreat身份安全云-TVD每日漏洞情报-2023-02-15
  • Unreal Engine角色涌现行为开发教程
  • vue处理一千张图片进行分页加载
  • (三十三)Vue之消息订阅与发布
  • Http中你必须知道那点事
  • ViewBinding使用入门
  • Retrofit源码分析实践(七)【Retrofit ConvertFactory的功能实现】
  • 介电常数常用测量方法综述
  • 重生之我是赏金猎人(三)-SRC漏洞挖掘-强行多次FUZZ发现某厂商SSRF到redis密码喷洒批量反弹Shell
  • 学会分享,学会生活,分享5款简单易用的软件。
  • Redux 与 Vuex 的区别总结
  • QT(15)- QFile
  • GaiaX开源解读 | 表达式作为逻辑动态化的基础,我们是如何设计的
  • python中adb shell相关操作
  • python 之 资源使用与控制 resource模块
  • 蓝库云|8项关键让你看透企业「数字转型」,零代码是惊喜
  • (五)、编辑页面-发布长文-富文本编辑【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】
  • 你是真的“C”——【经典面试知识点】数据在内存中的大小端存储方式
  • 从零开始的数模(二十六)单因素方差分析