我们希望通过注解(不提供 @Autowired)或 XML(不提供 default-autowire 或 bean 中的 autowire 属性) 的方式,在 IndexService 中,通过构造函数注入 UserService,那么 UserService 是否可以注入成功呢?

使用注解

  1. @Component
  2. public class UserService {
  3. }
  4. @Component
  5. public class IndexService {
  6. public IndexService(UserService userService){
  7. System.out.println(userService);
  8. }
  9. }
  10. @Configuration
  11. @ComponentScan("org.wesoft.spring.constructor")
  12. public class AppConfig {
  13. }
  14. public class App {
  15. public static void main(String[] args) {
  16. AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
  17. ac.register(AppConfig.class);
  18. ac.refresh();
  19. }
  20. }

运行结果如下:成功打印了 UserService,表示注入成功

  1. org.wesoft.spring.constructor.bean.UserService@dd3b207

使用 XML

XML 中没有指定任何自动装配模式,只是简单的指定了 2 个 bean

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
  4. >
  5. <bean id="indexService" class="org.wesoft.spring.constructor.bean.IndexService">
  6. </bean>
  7. <bean id="userService" class="org.wesoft.spring.constructor.bean.UserService">
  8. </bean>
  9. </beans>
  1. public class UserService {
  2. }
  3. public class IndexService {
  4. public IndexService(UserService userService){
  5. System.out.println(userService);
  6. }
  7. }
  8. @Configuration
  9. @ComponentScan("org.wesoft.spring.constructor")
  10. @ImportResource("classpath:applicationContext.xml")
  11. public class AppConfig {
  12. }

运行结果如下:成功打印了 UserService,表示注入成功

  1. org.wesoft.spring.constructor.bean.UserService@dd3b207

分析

你一定感到很奇怪,我们并没有使用 @Autowired 注解,也没有再 XML 中配置 default-autowire,那么 Spring 到底是如何做到的呢?

这就要从源码进行分析了,Spring 源码中有这么一段

  1. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  2. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
  3. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  4. return autowireConstructor(beanName, mbd, ctors, args);
  5. }

从源码来看,Spring 首先推断构造函数,然后判断构造函数是否不等于空,然后,再判断自动注入模型,是否等于 AUTOWIRE_CONSTRUCTOR,很明显,我们并没有指定 AutowireMode,所以这里是不成立的

如果我们有且只提供一个合理的构造函数,这里的合理是指,Spring 可以从容器中找到对应的 bean 作为入参,那么就可以完成注入,这里和注入模型并没有什么关系,只是 Spring 提供的一种构造方法注入技术而已,叫做推断构造函数

后期我会详细介绍,这里只是说明一下,构造函数为什么可以完成注入