• Spring面试题


    一、Spring面试题

    1、Bean的生命周期

    1.调用bean的构造方法创建Bean

    2.通过反射调用Set方法设 bean的属性

    3.如果Bean 实现了实现了BeanNameAware接口,Spring将调用setBeanName(),设置 Bean的name

    4.如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()把bean factory设置给Bean

    5.如果存在 BeanPostProcessor接口,Spring 将 调用它们的 postProcessBeforeInitialization(预初始化)方法,在Bean初始化前对其进行处理

    6.如果Bean 实现InitializingBean接口,spring将调用它的afterPropertiesSet方法,然后调用xml定义的init-method 方法,两个方法作用类似,都是初始化bean的时候执行

    7.如果存在beanPostProcessor,Spring将调用postProcessAfterInitialization(后初始化)方法,在Bean初始化后对其进行处理

    8.1 如果Bean为单例的话,那么容器会返回Bean给用户,并存入缓存池。如果Bean实现了DisposableBean接口,Spring将调用它的destory方法,然后调用在xml中定义的 destory-method方法,这两个方法作用类似,都是在Bean实例销毁前执行。

    8.2 如果Bean是多例的话,容器将Bean返回给用户,剩下的生命周期由用户控制。

    2.BeanFactory和FactoryBean的区别?

    1.BeanFacotry:管理Bean的容器,Spring中生成的Bean都是由这个接口的实现来管理的

    2.FactoryBean: 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,直接用xml配置比较麻烦,这时可以考虑用FactoryBean,可以隐藏实例化复杂Bean的细节

    3.BeanFactory和ApplicationContext有什么区别?

    BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

    两者区别如下:

    1、功能上的区别。BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。

    ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。

    2、加载方式的区别。BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

    而ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单例Bean,那么在需要的时候,不需要等待创建bean,因为它们已经创建好了。

    相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

    3、创建方式的区别。BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

    4、注册方式的区别。BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

    4.Bean注入容器有哪些方式?

    1、@Configuration + @Bean

    @Configuration用来声明一个配置类,然后使用 @Bean 注解,用于声明一个bean,将其加入到Spring容器中。

    @Configuration
    public class MyConfiguration {
        @Bean
        public Person person() {
            Person person = new Person();
            person.setName("大彬");
            return person;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2、通过包扫描特定注解的方式

    @ComponentScan放置在我们的配置类上,然后可以指定一个路径,进行扫描带有特定注解的bean,然后加至容器中。

    特定注解包括@Controller、@Service、@Repository、@Component

    @Component
    public class Person {
        //...
    }
     
    @ComponentScan(basePackages = "com.dabin.test.*")
    public class Demo1 {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
            Person bean = applicationContext.getBean(Person.class);
            System.out.println(bean);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3、@Import注解导入

    @Import注解平时开发用的不多,但是也是非常重要的,在进行Spring扩展时经常会用到,它经常搭配自定义注解进行使用,然后往容器中导入一个配置文件。

    @ComponentScan
    /*把用到的资源导入到当前容器中*/
    @Import({Person.class})
    public class App {
        public static void main(String[] args) throws Exception {
            ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
            System.out.println(context.getBean(Person.class));
            context.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4、实现BeanDefinitionRegistryPostProcessor进行后置处理。

    在Spring容器启动的时候会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,就是等beanDefinition加载完毕之后,对beanDefinition进行后置处理,可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。

    在下面的代码中,我们手动向beanDefinitionRegistry中注册了person的BeanDefinition。最终成功将person加入到applicationContext中。

    public class Demo1 {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            MyBeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = new MyBeanDefinitionRegistryPostProcessor();
            applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);
            applicationContext.refresh();
            Person bean = applicationContext.getBean(Person.class);
            System.out.println(bean);
        }
    }
     
    class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
            registry.registerBeanDefinition("person", beanDefinition);
        }
        
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5、使用FactoryBean接口

    如下图代码,使用@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,这里没有向容器中直接注入 Person,而是注入 PersonFactoryBean,然后从容器中拿Person这个类型的bean。

    @Configuration
    public class Demo1 {
        @Bean
        public PersonFactoryBean personFactoryBean() {
            return new PersonFactoryBean();
        }
     
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
            Person bean = applicationContext.getBean(Person.class);
            System.out.println(bean);
        }
    }
     
    class PersonFactoryBean implements FactoryBean<Person> {
        @Override
        public Person getObject() throws Exception {
            return new Person();
        }
    
        @Override
        public Class<?> getObjectType() {
            return Person.class;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    5.bean的作用域

    1、singleton:单例,Spring中的bean默认都是单例的。

    2、prototype:每次请求都会创建一个新的bean实例。

    3、request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。

    4、session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。

    5、global-session:全局session作用域。

  • 相关阅读:
    第二站:分支与循环(第二幕)
    MFC-工具栏
    CodeMirror实现类似input框的 placeholder提示效果
    定时任务调度(crond)
    GMTSAR软件InSAR时序处理流程
    171.Hadoop(七):Yarn的架构,工作机制,调度器,常用命令
    若依集成minio实现分布式文件存储
    【微服务】如何保证接口的幂等性
    苹果iOS App Store上架操作流程
    zabbix实现钉钉报警
  • 原文地址:https://blog.csdn.net/Afu1021/article/details/133781393