推文有个连结有解答我的疑惑
感谢bron大
文章有点长
先说说我对依赖注入的理解
Spring boot
依赖注入大致有三种方式
透过建构子的 透过setter的 或是 field
这三种都可以透过@Autowired注解来达到依赖注入的效果
我自己想到的建构子的举例是
假设有两个类 Address 和 Employee好了
1.
public class Address {
String Country;
String City;
String Street;
public Address(String country, String city, String street) {
Country = country;
City = city;
Street = street;
}
}
2.
public class Employee {
String sex;
String name;
Address address;
// 没有依赖注入的方式
public Employee(String Country,String City,String Street,String
sex, String name ) {
this.sex=sex;
this.address = new Address( Country, City,Street );
this.name=name;
}
// 有依赖注入的方式
public Employee(String sex, String name, Address address) {
this.sex = sex;
this.name = name;
this.address = address;
}
}
在上面的例子当中可以发现,如果哪一天
Address这个类新增了一个属性叫 phoneNumber好了
没有依赖注入的方式,必须要更改 Employee 的
this.address =new Address(Country,City,Street,phoneNumber)
而有依赖注入的方式确实降低了耦合
因为他不用更改Employee的建构方式
所以我理解依赖注入可以降低耦合
所以我理解依赖注入可以降低耦合
所以我理解依赖注入可以降低耦合
但我的问题是Spring boot 的 autowird annotation 有帮助我们降低耦合吗
在常见的开发中 我们经常都会有 Dao 以及 Service
假设我有两个 Dao 好了 分别是 Dao1 和 Dao2
以及一个Service
Dao1
public class Dao {
public void sayhi() {
System.out.println("hello");
}
}
Dao1
public class Dao {
public void sayhi() {
System.out.println("hello");
}
}
Dao2
public class Dao2 {
public void saygoodbye() {
System.out.println("say goodbye");
}
}
如果我不在service上面使用autowired
我的service会是
public class Service {
Dao1 dao=new Dao1();
Dao2 dao2=new Dao2();
public void sayhi() {
dao.sayhi();
}
public void saygoodbye() {
dao2.saygoodbye();
}
}
如果我使用了@Autowired注解
那我只是将
Dao1 dao=new Dao1();
Dao2 dao2=new Dao2();
替换成
@Autowired
Dao1 dao
@Autowired
Dao2 dao2
我想请问所以我使用了Autowired注解
我知道我可以不需要使用new 来建构实体
但 Spring 真的有帮我降低耦合吗
即使我换成 setter 配合 autowired的方式好了
那个 setter也是要我自己去撰写
Spring 帮我降低了耦合什么?
我的问题简单来说就是
我知道依赖注入可以降低耦合
但Spring boot透过 @Autowired注解帮我降低耦合在哪
谢谢
p.s 因为面试的时候常常被面试官问说懂不懂什么是
控制反转还有DI,我基本上举例都举 Address还有 Employee的例子
但当我反问下面例子的时候,他们好像也说要再回去想一下...
只有其中一个就说更复杂的例子会用到,但也没说什么是更复杂的例子QQ
作者: Keade0325 (pinpin) 2022-03-31 21:27:00
当有需要抽换实作的时候
作者:
MoonCode (MoonCode)
2022-03-31 21:29:00在你理解前应该先完全不靠 spring 的功能,只靠 java本身来做依赖注入,然后判断有没有真的有效就是你的类可以把依赖的东西改用mock替换。那等你都弄好后开始不断的堆积业务逻辑时,就会发现初始化的地方会有一堆 new constructor 然后再传进另一个 new constructor,那这时候一个像 spring 这样的框架就可以用各种方式来帮助你避免自己写这些 new,就可以避免一些麻烦。 但我是喜欢自己手动操作啦,靠框架的话整个生命周期很难看懂。
作者:
wulouise (在线上!=在电脑前)
2022-03-31 21:33:00我觉得任何DI framework都跟singleton 87%像邪恶
个人觉得方便测试时去 mock,平常用 Laravel 的经验
Polymorphism通常是autowired interface啦,再依参数配置决定要使用
作者: Keade0325 (pinpin) 2022-03-31 21:43:00
简单的例子就是更换DB driver
哪个实作上面那interface的component
@Autowired只是依类名或型别帮你在Spring容器生物件DI与IoC才是低耦合的关键,与@Autowired无关
可是如果DI要我自己写的话,Spring帮我做了啥,单纯的控制反转有降低耦合吗?
Spring帮你new物件并注入到使用的对象属性中还有上面Dao1 Dao2例子有误,DI是从外面set进来
我的第一个例子应该是DI吧,把ADDRESS注入到Employee当中即使用Spring,不用自己写new,可是建构子还是要自己写阿,降低了什么功夫呢
帮你搞定层层的依赖关系你可以试试不用Spring自己写依赖注入,你就知道差异
我第一个例子就没有依赖Spring 阿 地址跟员工那个
spring就是做掉你自己举的例子,不然谁要往两个class传dao进去?你后面举的自己new dao的行为,就等于你前面没有做DI的举例了
作者:
MoonCode (MoonCode)
2022-03-31 22:19:00我看下来只觉得原po写太少了 哈哈哈哈
今天是dao你感觉比较单纯无法,如果你要new的是service呢?视你的专案复杂度,一个service可能会有10几20个建构子需要你自己new出来,而service互相依赖不会只有有两个这样简单的情况
作者:
bluelink (淡水小面仔)
2022-03-31 22:33:00可以看看跟qualifier的搭配
作者:
kirin021 (kirin)
2022-03-31 22:40:00要以类别与类别间的关系来看是否降低耦合吧?降低耦合的定义应该不是叫大家可以少写code哈哈
不用@Autowired就要写上面连结中那坨new
20个dao只是一行吗?那你试试new 20个都有20个dao的service其实有在写mockito的应该都体会过,当service耦合太严重时,写test有多痛苦,最后都会顺便解耦XD
作者:
atpx (秋雨的心情)
2022-03-31 22:44:00你写工具给别人用比较会需要. 写商业逻辑不太用的到
作者: abadfriend (蓝色忧郁) 2022-03-31 22:46:00
不确定 @Qualifier 能不能解答到你的疑惑?
作者:
atpx (秋雨的心情)
2022-03-31 22:46:00运算的过程不想变动, 但又需要把产生的实例替换掉的情况下就用到你的例子
谢谢bron大,我好像懂了,qualfied还在看@@
不懂正常,因为例子太烂,简单的new感受不到这东西的用处你试试"new"个jdbc connection就知道了
会有spring好像没干事的错觉,是因为作者是你自己,你可以掌控那些复杂的service建构子,当多人协作时有人需要使用你的service,还需要搞懂那些建构子的逻辑跟用法,那就是一场灾难,更别提那个人的service立刻又跟那些建构子用途的物件耦合,每个人都这样就没完没了
重点在 依赖于接口 而不依赖于实作要能自己 new, 就绑死实作的 package/class 了给 spring 生, 自己只绑接口定义 实作就可替换
作者: s06yji3 (阿南) 2022-04-01 00:16:00
降低耦合和少写code是两回事
作者:
tttkkk (学到。)
2022-04-01 00:24:00整篇看完了 你要补的地方是 code to interface 的概念先了解 interface 再来看 dependency injection 会较易懂例如你有个 Dao interface 他有两个实作 Dao1 和 Dao2用 DI 可以在你的 Service 里面去指定用哪一个实作其实你举的 service 例子不是解耦合喔 试想你若真的要在service 中同时用到 Dao1 跟 Dao2 那怎会有解偶合的问题当你会需要偶尔使用Dao1 偶尔使用 Dao2 甚至未来改成Dao3才会需要解耦合 因为你把 Service 跟 Dao 解耦合了更改 Dao 实作时 就不会动到 Service
你第一个例子,地址,通常不会视为DI吧,比较像ddd的value object
我也有类似的问题,如果建构子会吃参数如果要在spring上是不是最好改写为另外set进去比较好不然常常会写一堆bean,好像没有比较方便但如果要用时再抓来set,物件的命名又会很混乱
一句话:DI并不解决耦合问题,DI只是帮助你更轻松的测试并且转换实作的时候不需要大量改动code
不管是依赖接口别依赖实作,还是用DI,都是解决掉你的耦合问题,才有后续带来的轻松测试跟切换实作,避免大量改动code,他们都是解耦过程的一部分
作者:
sharek (...)
2022-04-01 09:22:00会感觉不到DI好处,大概只能亲身经历过痛过强耦合的project才比较能体会
作者:
ssccg (23)
2022-04-01 10:25:00@Autowired找到完全同一个concrete class的bean来注入本来就没有降低耦合,可以找到相容的实作(实作interface的bean或subclass的bean)才有降低耦合
作者:
tw11509 (John-117)
2022-04-01 10:40:00Autowired接口,搭配profile注解,可以在不同环境使用不同实作关于di,spring in action有个骑士出任务的范例,还蛮有趣的
你可以A一下91哥的文 id是landlord他有个土砲重构的范例满不错的
作者: MonyemLi (life) 2022-04-01 18:42:00
spring 只是稍微降低耦合。主要降低的是多用接口,多写几层
作者: superpandal 2022-04-01 23:51:00
不想讲但还是讲一下好了 它就只是侦测你包内的annotation并且储存起来(map) 需要的时候取用初始化而已 依赖注入本身不是问题 问题是使用annotation的依赖注入 专案大了以后 一堆初始化流程你都不见得能够掌握 更别说annotation设值所造成的影响然后这样的初始化效能肯定比你直接new来的差接口的话更是扯 你直接改个类不就得了... 当然如果习惯非常好 用annotation也都无所谓 但你不一定是一一个人开发用这些框架有时候就不是人在使用工具 是人被工具玩更准确的是人写工具的恶意 而非工具本身自主无脑开发你才有人生 耗在这没意义的事情才糟糕
作者:
ssccg (23)
2022-04-02 10:32:00楼上肯定没用到request、session、refresh scope才会觉得spring DI只是个map存起来这么简单
作者: superpandal 2022-04-02 22:42:00
当然不是讲的这么大致方向 剩下的就只是应用再应用讲的这些真的要自己写框架不难写只是个人不会遇到一个问题解决了再创造一个名词光看这些其实很容易眼花撩乱 还是学习真的知识比较好
作者:
CoNsTaR ((const *))
2022-04-03 10:31:00Java 哈哈 JavaOld school try hard language搞笑的语言就是只能搞笑
作者:
tw11509 (John-117)
2022-04-03 21:17:00去除掉springBoot,IoC、DI和DIP这些概念又不是Java独有,说Java搞笑跟这篇文章的关联真是无法理解!?
作者:
CoNsTaR ((const *))
2022-04-04 13:21:00楼上找给我看除了 Java 以外还有哪个语言什么事都要 annotations ,设定档,框架魔法和 reflection 才能做的?真的笑死
作者:
tw11509 (John-117)
2022-04-04 21:15:00嗯嗯,您说得对