springboot的bean注入方式

425 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

常见的三种注入方式,代码如下:

@Service("checkService")
public class CheckServiceImpl implements CheckService {
     //方式一注入
     @Autowired
     private LogService logService;
	
     //方式二setter方法注入
     private LogService logserv;
     
     
     //方式三构造方法注入
     private static LogService logs;
 
     public boolean doCheck(Object obj) {
         System.out.println("CheckServiceImpl.doCheck");
         logService.doLog();
         return false;
     }

     //setter方式注入
     public  void setLogServ(LogService logService) {
         CheckServiceImpl.logserv = logserv;
     }
	 
     //构造方法注入
     public CheckServiceImpl(LogService logserv){
         this.logs = logserv;
     }
}

1.构造器注入

构造注入是Spring官方推荐使用的注入方式,但平时开发中很少使用这种方式。一般在有静态方法需要使用注入的对象时使用构造器注入的方式, 构造注入可以解决字段注入对外部不可见、无法注入不可变对象的问题,但是构造注入也有缺点。如果注入的对象较多,那么构造函数就会变得臃肿,可读性较差。构造注入无法解决循环依赖的问题,因为解决循环依赖需要用到三级缓存,对象放入三级缓存是在创建对象之后进行的,所以构造注入无法利用三级缓存解决循环依赖的问题。

    //方式三构造方法注入
     private static LogService logs;
 
     //构造方法注入
     public CheckServiceImpl(LogService logserv){
         this.logs = logserv;
     }

构造器注入可以是使用lombok包里面注解 @RequiredArgsConstructor,添加在类上,这个时候我们定义的字段需要是final类型:


@RequiredArgsConstructor
public class CheckServiceImpl implements CheckService {
    
    private final LogService logService;
}   

2.字段注入

字段注入是平时开发中最常使用的注入方式,因为简单方便,可读性强。但是Spring官方不建议我们使用这种注入方式. 注入的字段对外部不可见:类中的字段访问修饰符都是private,如果不添加get/set方法,对外是不可见的。这时该字段只能由Spring进行操作,我们是访问不了的,与容器的耦合度太高,而且不符合Java开发规范。无法注入不可变的对象:字段注入的时机是在对象创建之后进行的,如果注入的字段是final,则无法进行注入。

     //方式一注入
     @Autowired
     private LogService logService;

@Autowired注解也可以用@Resource注解代替,但是二者却又不同:

首先、@Autowired注解由Spring提供,只按照byType注入; @resource注解由J2EE提供,默认按照byName自动注入。

其次、@Autowired默认按类型进行装配,@Resource默认按照名称进行装配。

还有、@Autowired默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性false。如果想使用名称装配可以结合@Qualifier注解进行使用; @Resource默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行名称查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

3.setter方法注入

 setter方法注入综合了字段注入与构造注入的优缺点,既不会像构造函数注入那样臃肿,也不会像字段注入那样不符合JavaBean规范。它可以解决循环依赖的问题,但是也不能注入不可变的对象。

    //方式二setter方法注入
     private LogService logserv;
     


     //setter方式注入
     public  void setLogServ(LogService logService) {
         CheckServiceImpl.logserv = logserv;
     }