面试了才知道初始化Bean不仅只有new那么简单

简介: 面试了才知道初始化Bean不仅只有new那么简单

@PostConstruct 标注方法

所有我们来讲解一下如果使用@PostConstruct 标注方法来初始化Bean

一、首先我们先创建一个初始化对象

/**
 * @author Java面试教程
 * @date 2022-11-22 21:37
 */
public interface UserFactory {
}
/**
 * @author Java面试教程
 * @date 2022-11-22 21:37
 */
public class DefaultUserFactory implements UserFactory{
    //基于@PostConstruct注解
    @PostConstruct
    public void init(){
        System.out.println("DefaultUserFactory 初始化中...");
    }
}

二、把UserFactroy注册为bean

@Configuration
public class Demo {
    @Bean
    public UserFactory createUserFactory(){
        return new DefaultUserFactory();
    }
}

这里使用@Configuration是为了初始化的时候使用applicationContext.register(Demo.class),让程序把@Bean扫描到然后把Bean注册进去。

三、初始化Bean

@Configuration
public class Demo {
    public static void main(String[] args)
    {
        //创建BeanFactory容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //注册当前类,主要目的是获取@Bean
        applicationContext.register(Demo.class);
        //启动应用上下文
        applicationContext.refresh();
        //依赖查找
        UserFactory bean = applicationContext.getBean(UserFactory.class);
        //关闭应用上下文
        applicationContext.close();
    }
    @Bean
    public UserFactory createUserFactory(){
        return new DefaultUserFactory();
    }
}

运行的是@PostConstruct这个方法会被自动回调,打印出我们设置好的内容。

Connected to the target VM, address: '127.0.0.1:52103', transport: 'socket'
DefaultUserFactory 初始化中...
Disconnected from the target VM, address: '127.0.0.1:52103', transport: 'socket'

自定义初始化

为了区分不同的初始化,我们这里定义一个方法来执行

public interface UserFactory {
    void initUserFactory();
}
/**
 * @author Java面试教程
 * @date 2022-11-22 21:37
 */
public class DefaultUserFactory implements UserFactory{
    //基于@PostConstruct注解
    @PostConstruct
    public void init(){
        System.out.println("DefaultUserFactory 初始化中...");
    }
    public void initUserFactory(){
        System.out.println("自定义初始化方法 initUserFactory()...");
    }
}

这里我们自定义一个initUserFactory方法,然后把方法名放到@Bean注解中。

@Configuration
public class Demo {
    public static void main(String[] args)
    {
        //创建BeanFactory容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //注册当前类,主要目的是获取@Bean
        applicationContext.register(Demo.class);
        //启动应用上下文
        applicationContext.refresh();
        //依赖查找
        UserFactory bean = applicationContext.getBean(UserFactory.class);
        //关闭应用上下文
        applicationContext.close();
    }
    @Bean(initMethod = "initUserFactory")
    public UserFactory createUserFactory(){
        return new DefaultUserFactory();
    }
}

这样就会打印出来两个初始化方法的内容

Connected to the target VM, address: '127.0.0.1:53619', transport: 'socket'
DefaultUserFactory 初始化中...
自定义初始化方法 initUserFactory()...
Disconnected from the target VM, address: '127.0.0.1:53619', transport: 'socket'

实现InitializatingBean接口的afterPropertiesSet()方法

我们要去实现Spring它自己的一个接口,通过覆盖InitializatingBean接口的afterPropertiesSet方法。

public class DefaultUserFactory implements UserFactory, InitializingBean {
    //基于@PostConstruct注解
    @PostConstruct
    public void init(){
        System.out.println("DefaultUserFactory 初始化中...");
    }
    public void initUserFactory(){
        System.out.println("自定义初始化方法 initUserFactory()...");
    }
    @Override
    public void afterPropertiesSet() throws Exception
    {
        System.out.println("InitializingBean的afterPropertiesSety()...");
    }
}

运行后发现,三种方式共存且存在一定顺序

Connected to the target VM, address: '127.0.0.1:54298', transport: 'socket'
DefaultUserFactory 初始化中...
InitializingBean的afterPropertiesSety()...
自定义初始化方法 initUserFactory()...
Disconnected from the target VM, address: '127.0.0.1:54298', transport: 'socket'

它们的优先级:@PostConstruct注解 > 实现InitializatingBean接口的afterPropertiesSet()方法 > 自定义方法初始化

它们的顺序在任何spring版本都不会变化的。

结束语

关于Bean的实例化和初始化,现在业务开发中或许已经用不到了,但是如果你的目标是深耕于Java领域的话,那么以后难免涉及框架的二次开发,那么Bean的实例化和初始化就有必要提前的好好了解一下。

相关文章
|
SQL 数据库
SQL面试50题------(初始化工作、建立表格)
这篇文章提供了SQL面试中可能会遇到的50道题目的建表和初始化数据的SQL脚本,包括学生、教师、课程和成绩表的创建及数据插入示例。
SQL面试50题------(初始化工作、建立表格)
【Java基础面试三十二】、new String(“abc“) 是去了哪里,仅仅是在堆里面吗?
这篇文章解释了Java中使用`new String("abc")`时,JVM会将字符串直接量"abc"存入常量池,并在堆内存中创建一个新的String对象,该对象会指向常量池中的字符串直接量。
|
消息中间件 安全 Java
面试官:单例Bean一定不安全吗?实际工作中如何处理此问题?
面试官:单例Bean一定不安全吗?实际工作中如何处理此问题?
213 5
|
JavaScript 前端开发 Java
【面试题】new 一个对象时,js 做了什么?
【面试题】new 一个对象时,js 做了什么?
148 0
|
JavaScript 前端开发 编译器
面试官问我new Vue阶段做了什么?
面试官问我new Vue阶段做了什么?
118 0
|
架构师 Java 开发者
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
在40岁老架构师尼恩的读者交流群中,近期多位读者成功获得了知名互联网企业的面试机会,如得物、阿里、滴滴等。然而,面对“Spring Boot自动装配机制”等核心面试题,部分读者因准备不足而未能顺利通过。为此,尼恩团队将系统化梳理和总结这一主题,帮助大家全面提升技术水平,让面试官“爱到不能自已”。
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
568 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
【Java基础面试二十八】、使用字符串时,new和““推荐使用哪种方式?
这篇文章讨论了在Java中使用字符串时,推荐使用双引号`""`直接量方式而不是使用`new`操作符,因为`new`会在常量池之外额外创建一个对象,导致更多的内存占用。
|
开发工具 Python
2024年最新【Python】Python的二维数组初始化,2024年最新15个经典面试问题及答案例子
2024年最新【Python】Python的二维数组初始化,2024年最新15个经典面试问题及答案例子
2024年最新【Python】Python的二维数组初始化,2024年最新15个经典面试问题及答案例子
|
前端开发 Java 编译器
Java面试题:描述Java类的加载过程,包括加载、链接、初始化等阶段。
Java面试题:描述Java类的加载过程,包括加载、链接、初始化等阶段。
112 0