@Autowired由Spring框架定义,用于描述类中的属性后者方法(构造方法,set方法)。
Spring框架在项目运行时假如发现由它管理的Bean对象中有使用@Autowired注解描述的属性或者方法,会按照指定规则为属性赋值(DI)。
注入规则
首先检测容器内是否有与属性或方法参数类型相匹配的对象,假如有并且只有一个就直接将这个类型的对象生成注入到属性或方法参数中。
证明此结论的方法首先我们创建一个接口,因为是测试用的所以接口中可以不用写方法~~~~
再创建一个实现此接口的类比如SoftCache~~~~
在该类上面添加一个@Component注解,用来表示该类的对象交给Spring框架来管理(创建,使用,存储,销毁)。
然后我们再写一个测试类用来测试@Autowried这个注解的作用~~~~
在这个测试类上面要写上这个@SpringBootTest这个注解,表示该测试类由spring框架管理,但是这个类的对象不会存在Bean池中,因为测试类的作用域默认是多例模式(prototype),在类中声明一个属性,属性类型为刚刚创建的接口类型,这里的属性名可以先随意。
再创建一个方法,方法上面要添加注解@Test表示单元测试,方法体里的内容是输出这个属性的值,如果属性没有赋值则输出的值为null。
这个时候我们运行testCache这个方法,控制台打印输出结果为null。
因为我们没有给这个属性上面添加一个@Autowried注解,也没有在这个属性名字后面给它赋值,所以打印输出的结果是默认值null(引用类型变量)
解决方法可以在该属性上面添加一个@Autowired注释,然后spring框架就会为我们生成这个属性类型的实现类对象再打印输出结果是:
输出的结果是这个对象的实现类名字和地址值。
FAQ
1)当一个接口的实现类有多个时,这个接口类型的属性会怎么创建对象呢?
创建一个新的实现类,实现Cache接口,同样的在该类上面添加一个注解@Component表示将这类的对象交给spring管理,然后运行Test方法。
2)当一接口的实现类不止一个时,如果我们不指定生成哪个实现类类型,Test运行后会报错: No qualifying bean of type 'com.cy.pj.common.cache.Cache' available: expected single matching bean but found 2: softCache,weakCache
该错误的意思是,该属性可以创建的实现类不唯一,也就是有多个实现类,Spring框架底层不知道你想要哪个实现类对象,所以我们需要使用@Qualifier注解,这个注解作用是来指定你要创建的实现类是哪个。
@Qualifier注解里可以写你想要的实现类类名首字母小写其它该大写的地方大写(驼峰命名法)这样spring框架就知道你想要哪个实现类生成对象,打印输出的结果是。
注意@Qualifer里面写的实现类一定要是实现了你声明的属性的类型的实现类才行,否则会报错。
并且此注解要配合@Autowired注解使用,否则无法注入值,输出还是null。
如果不想用@Qualifer还有另一种写法就是将声明的属性的属性名写成实现类的类名同样的首字母小写其它该大写的地方大写。
无参构造注入
@Autowired还可以运用在构造方法上(无参,有参都可以),我们来测试这个方法,首先重新创建一个类不需要实现Cache接口,同样的在这个类上加上一个@Component注解让spring框架来管理这个类的对象,在这个类中我们声明一个Cache接口类型的属性,并写一个无参构造方法,和一个返回值是Cache类型的方法。
然后我们在写一个测试类用来测试SeaSerivce这个类是否能注入值,这个测试类上面要写一个@SpirngBootTest注解表示这个测试类交个Spring框架管理,这个测试类里声明一个SeaSerivce类型的属性由于这个类型的类不是接口所以可以创建这个类的对象(由Spring容器创建)。属性上要加上@Autowired注解,然后在写一个测试方法,方法体的内容是输出打印在SerSerivce类中Cache这个接口类的属性的值,通过我们在SeaSerivce类中提供的get方法。
输出打印后我们看到打印的结果为null,并且除了无参构造方法执行了,还另外执行了一个我们没有写的方法就是setCache方法。
当我们在调用getCache这个方法时Spring框架会先扫描被Component注解过的所有类,在扫描这些类下面是否有@Autowired注解有的话就为他们赋值。由于我们的Cache cache这个属性上没有写@Autowired注解所以没有自动注入值,打印输出结果为空。如果我们直接写上@Autowired在这个属性上,运行后会报错,原因和上面的错误是一样的非唯一的实现类。所以我们要用set方法来指定用哪个实现类。
注意要把属性上面的@Autowired注释或者删除掉,否则Spring扫描到后会直接报错不会继续扫描下面的内容,报错原因也是非唯一实现类。
在set方法上添加一个@Autowired注解并且在参数中要使用@Qualifier指定哪个实现类,一般无参构造会配合set方法使用。
有参方法注入
在Seaservice类中写一个有参构造方法,有参构造方法上的@Autowired可以省略不写,需要在参数中指定实现类对象。我们知道在创建一个对象时(new一个对象)会自动调用这个对象的无参构造,如果这个对象里面没有任何构造方法,java也会为我们创建一个无参构造方法只是我们看不见,但是当我们有了任意一个有参构造,那么java就不会为我们创建无参构造,我们可以自己写上去,在SpringBoot中如果一个类里没有无参构造方法,然么会默认执行有参构造方法这是SpringBoot测试类中启动的一个特性。
**这就是@Autowired注解的介绍,初学SpringBoot还有很多地方写的不够严谨,如果有问题可以在评论区提出,我会翻阅资料查改。**
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。