Purpblue原创文章,欢迎转载,但请保留本文的csdn链接:基于注解处理器(APT)的Spring注入统一与简化(一)--@Pbwired-CSDN博客
亦欢迎各位友好讨论、指正。
一晃出差也快半年了,感觉自己就是个上班机器,一直忙。现在项目上线在即,之前计划的文章终于慢慢有时间写了。
这次介绍的是我用空余时间自己搞的一个玩意,用于spring中的注入统一与优化,包括Bean注入与值注入(兼容静态变量),所以Bean注入的注解就叫@Pbwired好了,反正和Autowired脱不了干系嘛。至于值注入的注解,也就顺便叫@Pbvalue了,它的介绍在下一篇文章中。关于原理的一些介绍,那就在更后面的文章中了。
此文章的修改历程如下:
2020-09-07 首次发布
2020-09-08 修改
2020-09-12 再次修改
最近一次修改(2020-09-12)的原因是因为最初发布jar包的时候,尚未完全解决构造函数注入时自动为变量添加final修饰的情况,现在1.0.4版已处理完此问题。
一、用途
对于spring,至少我们可以讲出三种注入方式:注解注入、构造函数注入、setter注入。这三种方式中,最方便的自然就是@Autowired/@Resource之类的注解注入了,非常简单,但是呢,在IDE中,当把鼠标放在@Autowired上的时候,这提示有些让人不开心:
看吧,Spring Team recommends都来了(吓人呢?),叫我们总是用基于构造函数的依赖注入(好处有很多,不在本文讨论)……我当然也想啊,但是构造函数注入的那一大砣代码,总是让我望而却步。来嘛,比一下:
注解注入:
@Autowired
private IService service; //好了,我的注入写完了!
构造函数注入:
private final IService service;
@Autowired
public MyController(IService service) {
this.service = service;
}
这……还需要对比不?尤其当需要注入的bean很多的时候,那构造函数看起来叫一个酸爽。所以啊,构造函数注入,好是好,就是难看。好看的皮囊只要两行,有趣的灵魂硕大一砣。怎么办,选哪个?其实吧,小孩子才做选择题,成年人都要!
二、源码地址:GitHub - wbzdwjsm/pbwired: Simplify your injection in Spring, even constant injection.
如果您方便的话,麻烦点个Star呗,先谢了!关于它的相关介绍说明,后续我会写文章。
三、使用方式
相关jar包已传至中央仓库,github页面上的readme也已经注明,只需要在您的pom文件里作如下引入并且在IDE中允许注解处理器即可使用:
<dependency>
<groupId>com.purpblue</groupId>
<artifactId>pbwired</artifactId>
<version>1.0.4</version>
<scope>provided</scope>
</dependency>
四、正式介绍
@Pbwired支持两种注入方式:构造函数注入与setter注入。
先看一下,直接用@Pbwired代替@Autowired:
@Pbwired
private MyFirstService myFirstService; //对,就这样,像@Autowired一样!
看起来换汤不换药?没事,不要在意外表……毕竟真正跑起来的时候还得看装着灵魂的.class文件不是。
找到生成的.class文件,直接反编译查看:
private final IService service;
@Autowired
public MyController(IService service) {
this.service = service;
}
怎么样,还行吧?一个注解@Pbwired解决,你只管浪!
如果指定Bean名字呢?如果想用@Pbwired注解将注入方式变成setter注入呢?如果和其他用@Autowired/@Resource/setter/constructor注入的Bean一起使用呢?通通没问题!
上代码:
//会被添加到构造函数中,且指定Bean名firstService(前提是已提前定义此Component)
@Pbwired(name = "firstService")
private MyFirstService myFirstService;
//会单独使用setter注入
@Pbwired(wireType = WireType.SETTER)
private MySecondService mySecondService;
//原始的@Autowired
@Autowired
private MyThirdService myThirdService;
//原始的@Resource
@Resource
private MyFourthService myFourthService;
//myFifthService正常用构造函数直接注入,请注意下面的构造函数
private final MyFifthService myFifthService;
//mySixthService正常用setter注入,请注意下面的setter方法
private MySixthService mySixthService;
@Autowired
public MyController(MyFifthService myFifthService) {
this.myFifthService = myFifthService;
}
@Autowired
public void setMySixthService(MySixthService mySixthService) {
this.mySixthService = mySixthService;
}
会发生的事情我已经在代码里注释了,不过还是真实看一看编译好的.class字节码反编译出来的样子:
//这个是@Pbwired修饰的
private final MyFirstService myFirstService;
//这个是@Pbwired修饰但是指定了使用setter注入
private MySecondService mySecondService;
//普通的@Autowired
@Autowired
private MyThirdService myThirdService;
//普通的@Resource
@Resource
private MyFourthService myFourthService;
//原始就是构造函数注入,请注意下方构造函数的变化
private final MyFifthService myFifthService;
//原始setter注入,请注意下方的setter
private MySixthService mySixthService;
//仔细观察构造函数,myFirstService是不是已经被添加进来了,并且用@Qualifier指定了Bean名字?
@Autowired
public MyController(MyFifthService myFifthService, @Qualifier("firstService") MyFirstService myFirstService) {
this.myFifthService = myFifthService;
this.myFirstService = myFirstService;
}
//这个是原始的setter注入
@Autowired
public void setMySixthService(MySixthService mySixthService) {
this.mySixthService = mySixthService;
}
//看这里,因为@Pbwired指定了wireType = WireType.SETTER,所以这里生成了setter方法
@Autowired
public void setMySecondService(MySecondService mySecondService) {
this.mySecondService = mySecondService;
}
好了,我想说的已经全部在代码里和反编译出来的字节码里了,就那句话,只管浪!既要代码简洁,也要随心所欲!不过也友情提醒一句:构造函数注入虽好,但是在spring中相比注解注入和setter注入限制更多,灵活运用各种注入方式才是王道。因此,使用@Pbwired作构造函数注入时,需要遵循spring构造函数注入的一切约束。
欢迎各位看官帮忙测试,也恳请您提出宝贵看法,在此先行谢过!