• 大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)


    大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)


     

    现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法。一行 简单的注解就可以解决很多事情。但是,其实每一个注解背后都有很多值得学习和思考的内容。这 些思考的点也是很多大厂面试官喜欢问的内容。

    @Configuration处理类:org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition

    @Bean处理类:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition

    · 项目包结构

    F:.

    ├─java

    │ └─com

    │ └─example

    │ └─demo4

    │ │ Demo4Application.java

    │ │

    │ ├─configuration

    │ │ PersonConfiguration.java

    │ │ StuConfiguration.java

    │ │

    │ ├─controll

    │ │ StuController.java

    │ │

    │ ├─dao

    │ │ StuDao.java

    │ │ StuDaoImp.java

    │ │

    │ ├─entity

    │ │ Person.java

    │ │ Stu.java

    │ │

    │ └─server

    │ StuService.java

    │ StuServiceImp.java

    └─resources

    application.properties

    project.text

    · Beans依赖图

    ·

    ·

    问题1:@Configuration和@Component区别**(@Configuration自动cglib动态代理)**

    ·

    o @Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例(Spring启动时会专门处理@Configuration)。proxyBeanMethods可以设置成false,取消代理。除此之外以下@Bean无法动态代理。

    o 配置类必须以类的形式提供(不能是工厂方法返回的实例),允许通过生成子类在运行时增强(cglib 动态代理)。

    o 配置类不能是 final 类

    o 配置类必须是非本地的(即不能在方法中声明,不能是 private)。

    o 任何嵌套配置类都必须声明为static。

    o @Bean必须是单例(默认就是,别改成prototype)

    o @Component里面的@Bean不是代理的

    o 代理和不代理的区别如下代码:

    //拿到@Bean->person

    Person person = context.getBean(Person.class);

    //拿到组件

    PersonConfiguration personConfiguration = context.getBean(PersonConfiguration.class);

    //执行组件里面的person()方法

    Person person1=personConfiguration.person();

    //使用stu

    System.out.println(stu.getClass().getName());

    //获取组件里面的person()方法对象的hashCode

    System.out.println("person1:"+person1.getClass().getName() + "@" + Integer.toHexString(person1.hashCode()));

    //@Bean->person对象的hashCode

    System.out.println("person:"+person.getClass().getName() + "@" + Integer.toHexString(person.hashCode()));

    //从IOC容器中取出存在的personBean

    Map<String, Person> beansOfType = context.getBeansOfType(Person.class);

    //对比知道不代理执行组件里面的person()方法的对象不会被Spring管理,代理就会管理

    System.out.println("beansOfType:"+beansOfType.get("person").getClass().getName() + "@" + Integer.toHexString(person.hashCode()));

    ·

    问题2:expected single matching bean but found 2

    ·

    o

    同类型多个Beans,引发原因比如使用了context.getBean(Stu.class)、@Autowired只用ByType类获取或者注入Beans的时候

    o

    o

    使用名称获取,不优先使用ByType,==如果是其它第三方(也许第三方直接ByType)那么可以采取【禁止使用】或【优先使用】

    o

    o

    禁止使用

    o

    o @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })

    o application.properties里配置:spring.autoconfigure.exclude=全类名,全类名

    o

    优先使用(在设计层面不建议这样使用)

    o

    o

    @Bean

    @Primary

    public Person person() {

    return new Person();

    }

    o

    o

    ==正确姿态约定好命名规则尤为重要==

    o

    ·

    问题3:could not be registered. A bean with that name has already been defined in file

    ·

    o 组件重复问题,大多使用配置:spring.main.allow-bean-definition-overriding=true

    o 以上配置会覆盖Bean,并且依然产生具体对象

    具体底层实现类(谁定义存储了这些注册类??):

    ·

    AnnotatedGenericBeanDefinition:存储@Configuration注解注释的类

    ·

    ·

    ScannedGenericBeanDefinition:存储@Component、@Service、@Controller等注解注释的类

    ·

    ·

    spring初始化时,会用GenericBeanDefinition或是ConfigurationClassBeanDefinition(用@Bean注解注释的类)存储用户自定义的Bean,在初始化Bean时,又会将其转换为RootBeanDefinition

  • 相关阅读:
    语言特性-上下文对象
    语言特性-闭包
    语言特性-变量作用域
    语言特性-函数重载与类型检查
    面向对象的JS代码
    单例模式
    wait操作接口
    进程的创建模型
    模拟密码登陆过程
    目录操作的一些函数理解
  • 原文地址:https://www.cnblogs.com/QQ12538552/p/12378368.html
Copyright © 2020-2023  润新知