当前位置:首页 >> 智能终端演进 >> 【springboot原理篇】Bean的加载方式,面试必看,v5700(springboot bean加载过程)

【springboot原理篇】Bean的加载方式,面试必看,v5700(springboot bean加载过程)

cpugpu芯片开发光刻机 智能终端演进 5
文件名:【springboot原理篇】Bean的加载方式,面试必看,v5700 【springboot原理篇】Bean的加载方式,面试必看

🌈键盘敲烂,年薪30万🌈

目录

一、上古时代原始方式:

📕XML文件

~~bean定义

👀演示获取bean:

❌缺点:

📕注解方式:

~~@component

~~指定扫描路径:

👀演示获取bean

📕XML太繁琐: 

二、现代科技配置类

🐟配置类作用:

🐟@componentScan

🐟@configuration

👀演示获取bean

⭐本文重点,没有之一⭐

三、工厂模式FactoryBean

📕认识它

📕factorybean的优势:

📕小总结

四、超级无敌@import

📕应用场景:

📕@importResource

❓思考问题:

📕@import({类的字节码文件,……})

📕@import导入ImprotSelector接口

📕@import导入ImportBeanDefinitionRegistrar接口

📕@import导入BeanDefinitionRefistryPostProcessor接口 

五、register注册bean

📕register

六、总结


一、上古时代原始方式: 📕XML文件 ~~bean定义 配置自己的或者第三方的bean:id:指定bean的名称 class指定bean的位置 <!--声明自定义bean--><bean id="dog" class="com.itpan.domain.Dog"/><bean class="com.itpan.domain.Cat"/><!--声明第三方bean--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/>

 

👀演示获取bean: void te1(){ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationcontext1.xml");System.out.println(ctx.getBean("dog")); // 获取自定义baenSystem.out.println(ctx.getBean(Cat.class));System.out.println(ctx.getBean("dataSource")); // 获取第三方bean//获取所有的beanSystem.out.println("================");for (String name : ctx.getBeanDefinitionNames()) {System.out.println(name);}} ❌缺点:

太麻烦,且可读性太差,bean一旦多了就不知道哪些被加载了,哪些没被加载。

📕注解方式: ~~@component 只要在你的类上加上@component注解,就代表这个类要交给IOC容器管理但这还不够,java文件这么多,IOC不能所有文件都扫描一遍吧,所以还要在XML配置文件里面指定扫描路径。component(value = "可指定bean的名称") 等同于z在XML里面的id ~~指定扫描路径:

开启命名空间需要动5个地方:

👀演示获取bean @Testvoid te2(){// 通过注解加载的beanClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationcontext2.xml");System.out.println(ctx.getBean("dog")); // 获取自己的beanSystem.out.println(ctx.getBean("dataSource")); // 获取第三方的beanSystem.out.println("===============");// 获取容器中的所哟beanfor (String name : ctx.getBeanDefinitionNames()) {System.out.println(name);}} 📕XML太繁琐: 

XML文件里面的内容都是固定的,只有bean的定义不同,那么能不能省区XML文件呢???

 

二、现代科技配置类 🐟配置类作用:

配置类说白了就是加载bean的,当然配置类本身也会变为bean(重要),只要在配置类上加相应的注解,spring会自动扫描相应的包来加载bean。

🐟@componentScan

@componentScan就替代了XML里面那一大坨代码,但是扫描哪些包spring还不知道,所以要指定包扫描路径:@component({"指定扫描哪些包下的bean","xxx"})。

小细节:如果不加扫描路径,默认扫描本包及其子包下的类。

🐟@configuration

同上面的注解一样,它亦可以代替XML文件,表示该类是一个配置类,但是它们两个真的相同吗?

👀演示获取bean @Testvoid te3(){AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig1.class);for (String name : ctx.getBeanDefinitionNames()) {System.out.println(name);}}

注意:

获取配置类的bean是通过annotationconfigapplicationcontext这个对象的相关方法,那么@cofiguration与@componentScan有什么不同吗,如果相同用为什么会出现两个注解。

 

⭐本文重点,没有之一⭐ 相同点:加上这两个注解都会将该类变为配置类,成为IOC容器的bean,假如你获取bean的方式为annotationconfigapplicationcontext,那么这两个注解的作用一样。但是,如果你加载bean的方式是通过别的包扫描这个包,那么你不加@configuration这个注解就扫描不上,扫描不上就成为不了bean对象,到时候就干瞪眼了。

@configuration这个注解有个属性是proxybeanmethods,它的作用是使用哪种代理模式。

看完下面这个例子你就懂了

运行结果:

把proxybeanmethod改为false:

总结:

        当proxybeanmethods为true是,调用里面的方法创建的bean是代理对象调用的,也就是每一次调用方法如果IOC容器俩面有这个bean对象,就会使用这个对象,如果没有,new一个,以后用到了就会返回这个对象,所有三个bean对象一致。

        当proxybeanmethods为false是,代理对象每一次调用创建bean的方法都不会从IOC容器里面找,而是直接跑一遍代码,从而导致创建的三个bean对象不一致。

三、工厂模式FactoryBean 📕认识它

FactoryBean是我们创建了一个类,这个类专门用来造bean的,你可能会有疑惑,它和上面直接返回这个对象的那种方法有什么区别啊?就像下面这样

📕factorybean的优势:

来自gpt的肯定:

FactoryBean 提供了更高级别的配置和创建过程的控制,允许你以更灵活的方式管理和定制 Bean 的创建。它适用于那些需要特殊处理的 Bean 创建场景,而不仅仅是简单地实例化和配置对象。

📕小总结

并不是你返回值是什么就创建什么bean,例如factorybean就是创建的它的泛型的bean

四、超级无敌@import 📕应用场景:

假如一个很老的项目已经打包上线了,加载bean的方式XML,现在要新增功能,如何添加新的将那些bean导入呢??你不能修改原码依次加上各种注解吧,这不现实。。

就像下面这样:

运行后只有spring自带的bean:

📕@importResource

你只需加上这么一个注解,指定文件路径就欧啦!!

再次运行,熟悉的bean就回来了

❓思考问题:

假如你的spring中也定义了Dog这个bean,引入的XML文件也定义了Dog,那么会发生什么

结论:

XML文件的bean会覆盖spring中的bean

📕@import({类的字节码文件,……}) 使用improt注解导入的bean无需在该bean上加@component注解,并且使用import导入的bean的名称为类全类名,不再是什么方法的返回值了,这点要注意如果导入的是配置类,不光配置类被加载为bean,配置类里面的bean也被加载为bean。 @Configuration(proxyBeanMethods = false)@Import({Cat.class})public class SpringConfig3 {@Beanpublic Dog dog(){return new Dog();}}

注意:import只能使用一次,如果想导入多个bean,用,分割

📕@import导入ImprotSelector接口

可以做到bean的加载控制

public class MyImportSelect implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {// import导谁,形参就是谁System.out.println("提示" + importingClassMetadata);// 优势就是可以在这里面做判断,做到bean的加载控制boolean flag = importingClassMetadata.hasAnnotation("import org.springframework.context.annotation.Configuration");if (flag){return new String[]{"com.itpan.domain.Cat"};}return new String[]{"com.itpan.domain.Fish"};}} 📕@import导入ImportBeanDefinitionRegistrar接口

可以自定义bean的名称

public class MyRegister implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {// 构造一个beandefinition对象BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Fish.class).getBeanDefinition();registry.registerBeanDefinition("Jinyu", beanDefinition);}} 📕@import导入BeanDefinitionRefistryPostProcessor接口 

当IOC容器初始化所有的bean后,在加载这个类中的bean,也叫bean的后处理。

public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {// bean的后处理@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl2.class).getBeanDefinition();registry.registerBeanDefinition("bookService", beanDefinition);}} 五、register注册bean 📕register

容器初始化完成之后,可以手动注册bean

@Testvoid te7(){AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig3.class);SpringConfig3 springConfig3 = ctx.getBean("springConfig3", SpringConfig3.class);System.out.println(springConfig3.dog());ctx.registerBean("cat", Cat.class);System.out.println(ctx.getBean("cat"));} 六、总结

协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接