Spring @Autowired 用法

  • 首先看下@Component
  • ```举例 1 :```
  • ```举例 2 :```
  • 验证是否调用的是默认构造器
  • ```如何,在启动的时候执行有参数的构造函数??,这就要看@Autowired注解了!```
  • @Autowired注解


首先看下@Component

在类级别上添加了@Component注解,Spring在启动时就会找到该类(spring采用基于注解和类路径扫描的方式时),并为其生成一个实例,然后,纳入spring容器进行管理。

举例 1 :

参见:@Component @Bean @Configuration 用法

举例 2 :

代码如下(springboot项目):

package com.xl.test.logtest.annotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AutowiredTest {
	@Autowired(required=false)
	public AutowiredTest(Desk dk) {
		System.out.println("==================第一个@Autowired构造器执行================");
		System.out.println("==================dk================"+dk);
	}
	
	public AutowiredTest() {
		System.out.println("==================无参构造函数================");
	}
	
//	@Autowired(required=false)
//	public AutowiredTest(Desk dk, Bench bh) {
//		System.out.println("==================第二个@Autowired构造器执行================");
//	}
	
}

@Component
class Desk {
	
}

@Component
class Bench {
	
}

如上,类Desk上加上了注解Component, 在类AutowiredTest 中就可自动注入Desk的实例 dk:

springboot autowire springboot autowired怎么用_spring


启动项目,验证:

springboot autowire springboot autowired怎么用_springboot autowire_02


当然,这个实例是spring通过调用Desk的默认的无参构造器(也是当前唯一的一个构造器)生成的

验证是否调用的是默认构造器

在AutowiredTest中显示的声明无参/默认构造函数以及两个有参数的构造函数:

package com.xl.test.logtest.annotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AutowiredTest {
//	@Autowired(required=false)
	public AutowiredTest(Desk dk) {
		System.out.println("==================第一个@Autowired构造器执行================");
		System.out.println("==================dk================"+dk);
	}
	
	public AutowiredTest() {
		System.out.println("==================无参构造函数================");
	}
	
//	@Autowired(required=false)
	public AutowiredTest(Desk dk, Bench bh) {
		System.out.println("==================第二个@Autowired构造器执行================");
	}
	
}

@Component
class Desk {
	
}

@Component
class Bench {
	
}

启动项目,验证:只执行了默认的构造函数,其余两个并未执行

springboot autowire springboot autowired怎么用_spring_03

如何,在启动的时候执行有参数的构造函数??,这就要看@Autowired注解了!

@Autowired注解

Marks a constructor, field, setter method, or config method as to be autowired by Spring's dependency injection facilities

将构造器、域、setter方法或者配置方法标记为被注入的对象,也就是@Autowired注解可以用于构造器、域、setter方法或者配置方法上。当然,是通过Spring的依赖注入机制来完成依赖注入的。

根据官方文档,@Autowired注解分别对构造器、域、方法、参数等等做了详细解释,这里仅讨论构造器:

Only one constructor (at max) of any given bean class may declare this annotation with the 'required' parameter set to 
true, indicating the constructor to autowire when used as a Spring bean. If multiple non-required constructors declare 
the annotation, they will be considered as candidates for autowiring. The constructor with the greatest number of 
dependencies that can be satisfied by matching beans in the Spring container will be chosen. If none of the candidates 
can be satisfied, then a primary/default constructor (if present) will be used. If a class only declares a single constructor 
to begin with, it will always be used, even if not annotated. An annotated constructor does not have to be public.

当一个类是作为Spring的bean管理时,并且@Autowired的属性required为true(默认值)时,这个类的只能有一个构造函数能使用@Autowired注解: 那么,在启动项目时,会执行该构造器同时Spring会注入该构造器的参数实例(或者称为 依赖 ),如下所示:

package com.xl.test.logtest.annotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AutowiredTest {
	@Autowired
	public AutowiredTest(Desk dk) {
		System.out.println("==================第一个@Autowired构造器执行================");
		System.out.println("==================dk================"+dk);
	}
	
	public AutowiredTest() {
		System.out.println("==================无参构造函数================");
	}
	
//	@Autowired
	public AutowiredTest(Desk dk, Bench bh) {
		System.out.println("==================第二个@Autowired构造器执行================");
	}
	
}

@Component
class Desk {
	
}

@Component
class Bench {
	
}

启动项目,控制台打印如下:

springboot autowire springboot autowired怎么用_springboot autowire_05


延伸: 如果构造器中的参数实例(依赖)也就是 public AutowiredTest(Desk dk) 中的 dk为null(即是:Spring没有初始化并管理Desk的bean (dk) ),那么启动时会报错,如下:

将类Desk的注解@Component去掉:Spring就不会初始化Desk的实例了,其他的保持不变

package com.xl.test.logtest.annotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AutowiredTest {
	@Autowired
	public AutowiredTest(Desk dk) {
		System.out.println("==================第一个@Autowired构造器执行================");
		System.out.println("==================dk================"+dk);
	}
	
	public AutowiredTest() {
		System.out.println("==================无参构造函数================");
	}
	
//	@Autowired
	public AutowiredTest(Desk dk, Bench bh) {
		System.out.println("==================第二个@Autowired构造器执行================");
	}
	
}

//@Component
class Desk {
	
}

@Component
class Bench {
	
}

启动报错如下:

springboot autowire springboot autowired怎么用_spring boot_06


解决办法:

1、如上图

2、更改@Autowired的属性required的默认值,将其设置为false true:默认值,表示所需要的依赖必须存在

false:表示所需依赖可以不存在,但是不会执行该构造器,转而执行默认的构造器(需显示的声明默认构造器,否则,还是会报错:找不到Desk的bean),如下:

Description:

Parameter 0 of constructor in com.xl.test.logtest.annotation.AutowiredTest required a bean of type 
'com.xl.test.logtest.annotation.Desk' that could not be found.

验证如下:

package com.xl.test.logtest.annotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AutowiredTest {
	@Autowired(required=false)
	public AutowiredTest(Desk dk) {
		System.out.println("==================第一个@Autowired构造器执行================");
		System.out.println("==================dk================"+dk);
	}
	
	public AutowiredTest() {
		System.out.println("==================无参构造函数================");
	}
	
//	@Autowired
	public AutowiredTest(Desk dk, Bench bh) {
		System.out.println("==================第二个@Autowired构造器执行================");
	}
	
}

//@Component
class Desk {
	
}

@Component
class Bench {
	
}

springboot autowire springboot autowired怎么用_springboot autowire_07


此时,项目正常启动,但是,并没有执行@Autowired注解的构造器。

==小结:也就是只有提供了构造器的依赖实例(参数示例),才会执行构造器,那就是说@Autowired注解的属性required=true才有意义,因为required=false,如果有依赖就执行@Autowired注解的构造器; 没有依赖就执行默认的构造器(前提是:显示声明默认构造器!),但是没有执行@Autowired注解的构造器啊 ==

required=false真的没有意义吗? 不是的!,看下官方的文档:
If multiple non-required constructors declare the annotation, they will be considered as candidates for autowiring. The constructor with the greatest number of dependencies that can be satisfied by matching beans in the Spring container will be chosen.