Spring全家桶面试题(一)之Spring Framework(五)

三、Spring Beans(续)

30. Spring容器启动时,为什么先加载BeanFactoryPostProcess

1.因为BeanDefinition会在ioc容器加载的先注册, 而BeanFactoryPostProcess就是在所有的BeanDefinition注册完后做扩展的,所以要
先加载BeanFactoryPostProcess
2. 解析配置类的组件 它就实现BeanFactoryPostProcess, 所以要先去加载BeanFactoryPostProcess

31. Bean的创建顺序是什么样的?

Bean的创建顺序是由BeanDefinition的注册顺序来决定的, 当然依赖关系也会影响Bean创建顺序 (A-B)。

BeanDefinition的注册顺序由什么来决定的?

主要是由注解(配置)的解析顺序来决定:

  1. @Configuration mainConfig
  2. @Import+@Configuration mainConfig2
  3. @Component user(都是@Component的时候,按照类加载顺序)
  4. @Import—类 userImport
  5. @Bean userBean
  6. @Import—ImportBeanDefinitionRegistrar(手工注册bean)
  7. BeanDefinitionRegistryPostProcessor的方法注册的BeanDefinition最后

四、Spring注解

32. Spring有哪几种配置方式:

这里有三种重要的方法给Spring 容器提供配置元数据。

  1. XML配置文件。 spring诞生
    a. spring.xml
  2. 基于注解的配置。 Spring2.5+
    a. spring.xml @Component @Autowired
  3. 基于java的配置。 JavaConfig Spring3.0+
    a. @Configuration @Bean @ComponentScan…

33. 用过JavaConfig方式的spring配置吗?它是如何替代xml的?

基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。
以@Configuration 注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。
另一个例子是@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。

@Configuration
public class StudentConfig{ 
	 @Bean
	 public StudentBean myStudent(){
		 return new StudentBean();
	 } 
}

应用:

  1. 以前Xml
    a. Spring容器 ClassPathXmlApplicationContext(“xml”)
    b. Spring.xml
    c.
    d. 扫描包:
    e. 引入外部属性配置文件
    f.
    g. 指定其他配置文件:
  2. javaconfig
    a. Spring容器:AnnotationConfigApplicationContext(javaconfig.class)
    b. 配置类 @Configuration
    c. @Bean @Scope @Lazy
    d. 扫描包: @ComponentScan
    e. 引入外部属性配置文件 @PropertySource(“classpath:db.properties”)
    图灵课堂
    f. @Value(“${mysql.password}”)
    g. @Import @Import({配置类}) 使用比较灵活
    Spring全家桶面试题(一)之Spring Framework(五)_第1张图片

34. @Component, @Controller, @Repository, @Service 有何区别?

@Component是 @Controller、@Repository、@Service的元注解
@Controller、@Repository、@Service分别对应三层架构,@Controller标注在控制器上,@Repository标注在数据访问层,@Service标注在业务层

35. @Import可以有几种用法?

4种:

  1. 直接指定类 (如果配置类会按配置类正常解析、 如果是个普通类就会解析成Bean)
  2. 通过ImportSelector 可以一次性注册多个,返回一个string[] 每一个值就是类的完整类路径
    a. 通过DeferredImportSelector可以一次性注册多个,返回一个string[] 每一个值就是类的完整类路径
    区别:DeferredImportSelector 顺序靠后,在 BeanDefinitionRegistryPostProcessor的方法注册之前的位置。
  3. 通过ImportBeanDefinitionRegistrar 可以一次性注册多个,通过BeanDefinitionRegistry来动态注册BeanDefintion

36. 如何让自动注入没有找到依赖Bean时不报错

这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required
注解的bean属性未被设置,容器将抛出BeanInitializationException。

如何解决:将是否必须注入将默认的’是’改为‘否’

@Autowired(required = false) 
private Role role;

37. 如何让自动注入找到多个依赖Bean时不报错

多个类实现了LoginService接口,当运行

@Autowired
private LoginService loginService;

会报错,表示不止一个唯一的bean。
Spring全家桶面试题(一)之Spring Framework(五)_第2张图片

38. @Autowired 注解有什么作用

@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
@Autowired 注解提供了更细粒度的控制,不像by name,by type自动注入的方式(为所有提供了set()方法的属性自动注入),@Autowired 默认按照类型自动注入,如果类型匹配到多个再按照名字自动注入,不需要额外提供set()方法。

39. @Autowired和@Resource之间的区别

@Autowired可用于:构造函数、成员变量、Setter方法
@Autowired和@Resource之间的区别
@Autowired,Spring提供的,默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为
false)。
@Resource,JDK提供的,默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

40. 使用@Autowired注解自动装配的过程是怎样的?

记住:@Autowired 通过Bean的后置处理器进行解析的

  1. 在创建一个Spring上下文的时候在构造函数中进行注册AutowiredAnnotationBeanPostProcessor
  2. 在Bean的创建过程中进行解析
  3. 在实例化后预解析(解析@Autowired标注的属性、方法 比如:把属性的类型、名称、属性所在的类… 元数据缓存起)
  4. 在属性注入真正的解析(拿到上一步缓存的元数据 去ioc容器帮进行查找,并且返回注入)
    a. 首先根据预解析的元数据拿到 类型去容器中进行查找
  • 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
  • 如果查询的结果不止一个,那么@Autowired会根据名称来查找;
  • 如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。
    Spring全家桶面试题(一)之Spring Framework(五)_第3张图片

41. 配置类@Configuration的作用解析原理:

  1. @Configuration用来代替xml配置方式spring.xml配置文件
  2. 没有@Configuration也是可以配置@Bean
  3. @Configuration加与不加有什么区别
  4. 加了@Configuration会为配置类创建cglib动态代理(保证配置类@Bean方法调用Bean的单例),@Bean方法的调用就会通过容器.getBean进行获取

42. @Bean之间的方法调用是怎么保证单例的? ( @Configuration加与不加的区别是什么?)

  1. 如果希望@bean的方法返回是对象是单例 需要在类上面加上@Configuration,
  2. Spring 会在invokeBeanFactoryPostProcessor 通过内置BeanFactoryPostProcessor中会CGLib生成动态代理代理
  3. 当@Bean方法进行互调时, 则会通过CGLIB进行增强,通过调用的方法名作为bean的名称去ioc容器中获取,进而保证了@Bean方法的单例

43. 要将一个第三方的类配成为Bean有哪些方式?

第一种:@Bean
Spring全家桶面试题(一)之Spring Framework(五)_第4张图片
第二种:ImportSelector的实现类,注册selectImports返回的数组(类全路径)则IOC容器批量注册,但是不能控制实例化过程
第三种:@Import类,但是不能控制实例化过程
在这里插入图片描述
第四种:@Import ImportBeanDefinitionRegistrar的实现类,手工注册beanDefinition

@Import(MyImportBeanDefinitionRegistrar.class)

MyImportBeanDefinitionRegistrar类,手工注册

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        RootBeanDefinition beanDefinition=new RootBeanDefinition(DruidDataSource.class);
        beanDefinition.getPropertyValues().add("url","...");
        beanDefinition.getPropertyValues().add("username","root");
        registry.registerBeanDefinition("dataSource",beanDefinition);

    }
}

第五种:实现BeanDefinitionRegistryPostProcessor,手工注册BeanDefinition

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    //手工注册
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        RootBeanDefinition beanDefinition=new RootBeanDefinition(DruidDataSource.class);
        beanDefinition.getPropertyValues().add("url","...");
        beanDefinition.getPropertyValues().add("username","root");
        registry.registerBeanDefinition("dataSource",beanDefinition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

44. 为什么@ComponentScan 不设置basePackage也会扫描?

Spring在解析@ComponentScan的时候,拿到basePackage,如果没有设置,会将当前类所在的包的地址作为扫描包的地址

你可能感兴趣的:(后端,#,面试笔试,spring,java,后端)