每天五分钟,学透Spring《三、推断构造方法》

336 阅读4分钟

图片

做一个单纯的程序汪,分享干货,聊聊人生。

微信公众号:后端架构进阶

关注我发现更多的干货,微服务、Spring源码、JVM、SpringCloud Alibaba、K8S等。

如果你觉得本文对你有帮助,麻烦给我点个赞,感谢支持!

前面讨论了Bean的获取和创建的方式。今天继续讨论我们的Spring,前两篇没看的可以去看看。

每天五分钟,学透Spring《一、Spring中是如何获取Bean》

每天五分钟,学透Spring《二、Bean的创建过程》

一、什么是构造方法推断?

我们都知道,Spring在基于某个类生成Bean的过程中,需要利用该类的构造方法来实例化得到一个对象,但是如果一个类存在多个构造方法,Spring会使用哪个呢?最终选定使用哪个构造方法的过程就是构造方法推断。

二、推断逻辑

  • 如果一个类只存在一个构造方法,那么无论这个构造方法是无参还是有参Spring都会用这个构造方法。
/**
 * 构造推断
 *
 * @author AerCool Yang
 * @date 2021-12-11 14:09:56
 */
@Component
public class UserService {

    public UserService() {
        System.out.println("我是无参构造方法!");
    }

    public static void main(String[] args) {
        try (AnnotationConfigApplicationContext con = 
                     new AnnotationConfigApplicationContext(Config.class)) {
            Object userService = con.getBean("userService");
            System.out.println(userService);
        }
    }
}

我们可以看到输出了如下内容。

我是无参构造方法!
com.aercool.construct.UserService@54bff557

如果是有参呢?

/**
 * 有参构造推荐
 *
 * @author AerCool Yang
 * @date 2021-12-11 14:09:56
 */
@Component
public class UserService {

    public UserService(String name) {
        System.out.println("我是有参构造方法:" + name);
    }

    public static void main(String[] args) {
        try (AnnotationConfigApplicationContext con =
                     new AnnotationConfigApplicationContext(Config.class)) {
            Object userService = con.getBean("userService");
            System.out.println(userService);
        }
    }
}

可以看到报错了,因为去创建有参的Bean的时候,没有传入参数。

但是,如果上面既有有参又有有参,那么会使用无参的。无参的就是默认构造方法,所以为什么说如果我们创建了有参构造方法,必须把无参的构造方法也自己创建了。

但是如果我有参和无参都有,我要用有参构造方法要怎么使用呢?答案是:在要用的方法上加上@Autowired

/**
 * 有参和无参同时存在
 *
 * @author AerCool Yang
 * @date 2021-12-11 14:09:56
 */
@Component
public class UserService {

    public UserService() {
        System.out.println("我是无参构造方法");
    }

    @Autowired
    public UserService(String name) {
        System.out.println("我是有参构造方法:" + name);
    }

    public static void main(String[] args) {
        try (AnnotationConfigApplicationContext con =
                     new AnnotationConfigApplicationContext(Config.class)) {
            Object userService = con.getBean("userService");
            System.out.println(userService);
        }
    }
}

这个时候就会加载有参的构造方法了。

三、有参构造参数如何得来?

从上面我们可以看到,Spring会根据入参的类型和入参的名字去Spring中找Bean对象,如果找到,就会当作初始化该类的参数。如果没找到就报错了。我们来演示下可以找到的情况。

/**
 * 构造方法推断
 *
 * @author AerCool Yang
 * @date 2021-12-11 14:09:56
 */
@Component
public class UserService {

    public UserService() {
        System.out.println("我是无参构造方法");
    }

    @Autowired
    public UserService(OrderService orderService) {
        System.out.println("我是UserService的有参构造方法:" + orderService);
    }

    public static void main(String[] args) {
        try (AnnotationConfigApplicationContext con =
                     new AnnotationConfigApplicationContext(Config.class)) {
            Object userService = con.getBean("userService");
            System.out.println(userService);
        }
    }
}

上面的方法执行的结果是这样的:

OrderService的无参构造初始化了...
我是UserService的有参构造方法:com.aercool.construct.OrderService@2034b64c
com.aercool.construct.UserService@2b40ff9c

所以综上来说:

  1. 当去找userService的时候,第一次会去初始化userService;
  2. 初始化userService的时候,发现是用的有参构造,然后去找orderService,没有就去初始化;
  3. 然后把orderService给初始化了;
  4. 最终日志打印就是上面的效果了。

四、小结

作为Java开发,其实我们工作中时时刻刻都在使用我们的Spring,这些现象其实早就遇到过,只是可能没注意罢了。

好了,今天的文章就分享这么多。后面会分享事务、AOP相关内容,敬请期待!

历史文章汇总:包含Netty、源码、并发、JVM等

总结

以上就是今日内容的总结和分享,感谢各位大佬的 点赞关注收藏

微信公众号:后端架构进阶

更多文章正在赶来,喜欢记得给我点个 👍 ,感谢支持!

公众号文章同步更新!关注我,不迷路!