前些天新加入项目中的小伙儿写了一段代码,我看到之后,顿时以固有的经验来判断说:Spring的注解不能这样写,不够简洁云云。但本着对技术的钻研精神,还是深入分析比较了一下Spring的注解形式及优缺点。原来,大家最常用的注解方式不是最优的,而是最不推荐的。
使用Spring框架最核心的两个功能就是IOC和AOP。IOC也就是控制反转,我们将类的实例化、依赖关系等都交由Spring来处理,以达到解耦合、利用复用、利于测试、设计出更优良程序的目的。而对用户来说,操作最对的便是注解。在Spring中提供了三类注解方式,下面我们就逐一分析。最后,你会发现,你最常用、看起来最方便的形式确实最不推荐的一种形式。
@Controller public class FooController { @Autowired // @Resource private FooService fooService; }
此种注解方式,应用最广泛:
@Controller public class FooController { private final FooService fooService; private final FooService1 fooService1; @Autowired public FooController(FooService fooService,FooService1 fooService1) { this.fooService = fooService; this.fooService1 = fooService1; } }
或
@Controller public class FooController { private final FooService fooService; // 当只有一个参数时可不写@Autowired public FooController(FooService fooService) { this.fooService = fooService; } }
Spring4.x推荐的注入方式。对比Field注入:
@Controller public class FooController { private FooService fooService; @Autowired public void setFooService(FooService fooService) { this.fooService = fooService; } }
Spring3.x推荐的注入方式,但并没有被广泛应用,当初推荐的理由:
在上面的分析看来,构造函数注入好像并没有显现出来它的优势,但问什么Spring4.x会推翻之前推荐的setter注入,采用构造函数注入呢?官方的理由汇总如下:
如果有大量依赖需要注入说明该类的职责过于复杂,需要遵从单一性原则进行拆分;
存在即合理,根据具体情况可以采用最适合的方式。比如,可以同时使用 @Qualifier 来达到一些约束限定的目的。也可以使用setter注入和构造函数注入相结合的方式来进行注入。
Idea已经提供了相应的插件支持: