本文转载自微信公众号《苏三说科技》,作者苏三说科技。转载本文请联系苏三硕科技公众号。前言最近在review别人代码的时候,看到了@Autowired的一些不同用法。我觉得很有趣。我花了一些时间研究它,并获得了很多东西。现在,我将与您分享。也许@Autowired比你想象的更强大。1、@Autowired的默认组装我们都知道spring中的@Autowired注解是用来自动组装对象的。通常,我们在项目中使用这个:packagecom.sue.cache.service;importorg.springframework.stereotype.Service;@ServicepublicclassTestService1{publicvoidtest1(){}}packagecom.sue.cache.service;importorg.springframework.stereotype。Service;@ServicepublicclassTestService2{@AutowiredprivateTestService1testService1;publicvoidtest2(){}}是的,这样就可以拼装成功了,因为spring默认是按照type来拼装的,也就是我们所说的byType。另外@Autowired注解的required参数默认为true,表示开启自动组装。有时我们不想使用自动组装功能,可以将这个参数设置为false。2.当同类型的对象不止一个时,上面的byType方法主要是针对同类型的对象只有一个的情况。此时对象类型是唯一的,可以找到正确的对象。但是如果有多个相同类型的对象会怎样呢?在项目的test目录下,新建一个同名类TestService1:packagecom.sue.cache.service.test;importorg.springframework.stereotype.Service;@ServicepublicclassTestService1{publicvoidtest1(){}}重启项目时:Causedby:org.springframework.context.annotation.ConflictingBeanDefinitionException:Annotation-specifiedbeanname'testService1'forbeanclass[com.sue.cache.service.test.TestService1]conflictswithexisting,non-compatiblebeandefinitionofsamenameandclass[com.sue.cache.service.TestService1]结果是报错,报的类名有冲突,直接导致项目无法启动。注意这种情况不是两个同类型的对象被Autowired导致的,非常容易造成混淆。这是因为spring的@Service方法不允许类名相同,因为spring会将类名的首字母转为小写作为bean名,比如:testService1,默认情况下bean名必须是only。让我们看看如何生成两个相同类型的beans:}@Bean("test2")publicTestService1test2(){returnnewTestService1();}}在TestConfig类中手动创建一个TestService1实例,并去掉TestService1类上原有的@Service注解。重启项目:果然报错,说明testService1是单例,但是找到了两个对象。其实还有一种情况会生成两个相同类型的bean:;}项目重新启动时:图片报错,提示同上,testService1是单例,但是找到了两个对象。第二种情况在实际项目中出现的比较多。在下面的例子中,我们主要关注第二种情况。3、@Qualifier和@Primary明显在spring中,按照Autowired默认的组装方式:byType,解决不了上面的问题,那么可以改用按名称组装:byName。只需在代码中添加@Qualifier注解:@ServicepublicclassUserService{@Autowired@Qualifier("user1")privateIUseruser;}这样调整后,项目就可以正常启动了。合格者是指有资格的人。一般与Autowired结合使用。需要指定一个bean名,通过bean名可以找到需要组装的bean。除了上面的@Qualifier注解,@Primary注解也可以用来解决上面的问题。在User1上添加@Primary注解:@Primary@ServicepublicclassUser1implementsIUser{@Overridepublicvoidsay(){}}去掉UserService上的@Qualifier注解:@ServicepublicclassUserService{@AutowiredprivateIUseruser;}重启项目即可正常使用。当我们使用自动配置组装一个bean时,如果这个bean有多个候选,如果其中一个候选有@Primary注解修饰,那么这个候选就会被选为自动配置的值。4、@Autowired的使用范围上面例子中的@Autowired注解是用在成员变量上的,但是@Autowired的威力还远不及。先看@Autowired注解的定义:从图中可以看出,这个注解可以用在5种目标类型上。下面用一张图来总结一下:这个注解最常见的用法可能是在成员变量上。接下来我们重点看看在其他地方怎么用?4.1成员变量在成员变量上使用Autowired注解:@ServicepublicclassUserService{@AutowiredprivateIUseruser;}这个方法可能是最常用的。4.2构造函数在构造函数上使用Autowired注解:@ServicepublicclassUserService{privateIUseruser;@AutowiredpublicUserService(IUseruser){this.user=user;System.out.println("user:"+user);}}注意在构造函数上添加Autowired注解实际上使用的是Autowired装配方法,而不是构造函数装配。4.3方法为普通方法添加Autowired注解:@ServicepublicclassUserService{@Autowiredpublicvoidtest(IUseruser){user.say();}}spring会在项目启动过程中自动调用一次带有@Autowired注解的方法,我们可以通过该方法做一些初始化工作。也可以在setter方法中添加Autowired注解:@ServicepublicclassUserService{privateIUseruser;@AutowiredpublicvoidsetUser(IUseruser){this.user=user;}}4.4参数可以在带有Autowired注解的构造函数的参数中添加:@ServicepublicclassUserService{privateIUseruser;publicUserService(@AutowiredIUseruser){this.user=user;System.out.println("user:"+user);}}也可以给非静态方法的入参加上Autowired注解:@ServicepublicclassUserService{publicvoidtest(@AutowiredIUseruser){user.say();}}4.5这种注解的方式其实不太实用,就不过多介绍了。5、@Autowired的高端玩法其实上面的例子都是使用@Autowired来自动组装单个实例,这里我告诉大家它也可以自动组装多个实例。这是怎么回事?调整UserService方法,使用List集合接收IUser类型的参数:@ServicepublicclassUserService{@AutowiredprivateList
