Spring IOC如何通过何种机制实现降低系统组件间的耦合度?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1967个文字,预计阅读时间需要8分钟。
有同学在学习Spring框架时可能会问这样的问题:为什么通过依赖注入就能降低代码间的耦合呢?我通过new生产对象也可以啊,不就一行代码的不同吗?一个是用@Resource注解,一个是用new关键字。
实际上,依赖注入(DI)和直接使用new关键字创建对象在代码结构、可维护性和灵活性方面有着显著差异。以下是依赖注入的一些优势:
1. 降低耦合度:通过依赖注入,对象的创建和依赖关系由外部容器管理,减少了类之间的直接依赖,使得代码更加模块化,易于修改和扩展。
2.提高可测试性:依赖注入使得单元测试更加容易,因为可以更容易地替换依赖的对象。
3.灵活性和可配置性:依赖注入允许在运行时动态地改变对象的依赖关系,提供了更高的灵活性和可配置性。
使用@Resource注解或new关键字创建对象的具体区别如下:
- @Resource注解:这是一种基于Java注解的依赖注入方式,通常与Spring框架结合使用。它允许通过属性名或类型来注入依赖,代码简洁,易于维护。
- new关键字:直接使用new关键字创建对象,代码简单,但容易导致代码间耦合,难以进行单元测试和代码重用。总之,依赖注入是一种更高级、更灵活的编程方式,有助于提高代码质量。
有同学在学习 Spring 框架中可能会问这样的问题,为什么通过依赖注入就可以降低代码间的耦合呢?我通过 new 生产对象不也可以吗,不就是一行代码的不同,一个是 @Resource 注入,一个是 new 创建,怎么就降低耦合了?
今天博主就带大家来一步步剖析这个问题
一、传统方式创建对象通常我们是这样创建对象的
WuliCar wuli = new WuliCar();
wuli.run();
第一天:二明想用一辆车,然后通过 new 搞了一辆五菱荣光,调用 run 方法开始使用,车子跑起来了,很高兴。
一个月后:二明公司赚钱了,不想开五菱了,想换辆宝马,接下来二明一顿操作:
BaomaCar baoma = new BaomaCar();
baoma.run();
很好,车子从五菱换成了宝马,跑起来了,很高兴。
半年后:二明公司赚大钱了,二明想搞辆直升机,接下来又一顿操作
ZhiShenJi zhi = new ZhiShenJi();
zhi.fly();
这次改动比较大,宝马换成直升机,run 换成了 fly。
看到这里先思考一下,不想往下看,这样做有什么问题吗?
思考时间到,我们接着往下看。
从代码看好像没多大问题,不就改了两行代码嘛,这有啥。你想想,如果你的代码中有 1000 个地方都是这么写的,你想把宝马换成直升机岂不是要改 1000 次,run 改成 fly 又要改 1000 次,晚上别想下班了。
二、接口编程经过上次一顿操作,二明加了好几天班才弄完,二明想想每天这么搞不得累死,不行,得想想办法。于是二明脑子一转了,一想就想到了。我定义好一些方法,大家都按照这个规则来,不就好了。
public interface vehicle {
// 定义一个交通工具接口,有一个 work 方法
void work();
}
宝马实现这个接口:
public class Baoma implements vehicle {
@Override
public void work() {
System.out.println("宝马跑起来");
}
}
飞机实现这个接口:
public class ZhiShenJi implements vehicle {
@Override
public void work() {
System.out.println("直升机飞起来");
}
}
经过上面改造后,后面二明想把宝马换成直升机的时候只需要修改 new 那块就可以了,省了很多时间
利用接口确实好一些了,但是问题还是没有解决。为了提高内聚性,专职类负责特定的事情,所以我们使用一个类作为工厂类,既能生产 Car 又能生产 ZhiShenJi
class VehicleFactory{
VehicleFactory(){}
public static Vehicle getInstance(String type){
Animal result = null;
if("car".equals(type)){
result = new Car();
}
if("zhishenji".equals(type)){
result = new ZhiShenJi();
}
return result;
}
}
如果有一次我想锻炼身体,想骑自行车了,那么很简单
class VehicleFactory{
VehicleFactory(){}
public static Vehicle getInstance(String type){
Animal result = null;
if("car".equals(type)){
result = new Car();
}
if("zhishenji".equals(type)){
result = new ZhiShenJi();
}
if("zixingche".equals(type)){
result = new ZiXingChe();
}
return result;
}
}
Vehicle vehicle = VehicleFactory.getInstance("zixingche");
vehicle.work();
这种方法把创建对象的过程交给了一个专业的类(Factory),我只需要告诉他我需要什么(参数),他就会返回给我正确的对象,只是解决了内聚性的问题,但是他并没有解决我的声明语句七零八落的散落在程序中,我还是需要去将参数从car替换为zixingche
后来二明想到一个更绝妙的主意.我在写程序的时候不告诉工厂我需要什么,等到运行的时候我再告诉工厂我需要什么,再利用反射技术给我生产出来不就可以了吗?二明说干就干
Vehicle vehicle = VehicleFactory.getInstance(读取配置文件);
vehicle.work();
我想要的:zixingche
zixingche.work();
大功告成,这样我要什么,都写在一个配置文件中,利用反射技术就可以创建好,这样我就不用在生产了,下次换车的时候直接去配置文件中修改就好了,代码中不用修改。
对于生产对象这件和业务没有直接关系的事情,我们已经提取给了专业的工厂,专业的工厂还是根据配置文件进行的生产,想生产什么我只需要改一处即可,这就是降低了耦合性(生产对象和业务之间的耦合,让生产对象对业务的影响降到了最低)。
五、Spring IOC上面第四点说的那些功能,Spring IOC 已经帮助我们实现了,Spring IOC 就是利用工厂模式+反射实现自动生产对象,管理对象生命周期的功能。降低了代码的耦合
总结- 依赖注入的意思是你需要的东西不是由你创建的,而是第三方,或者说容器提供给你的。这样的设计符合正交性,即所谓的松耦合。
- 依赖注入是调用者仅通过声明某个组件就可以获得组件的控制权,而对该组件的依赖关系管理、查找、加载由外部完成。
- 依赖注入就是你不用关心对象的生命周期,什么时候被创建,什么时候销毁,只需直接使用即可,对象的生命周期由提供依赖注入的框架来管理。
本文共计1967个文字,预计阅读时间需要8分钟。
有同学在学习Spring框架时可能会问这样的问题:为什么通过依赖注入就能降低代码间的耦合呢?我通过new生产对象也可以啊,不就一行代码的不同吗?一个是用@Resource注解,一个是用new关键字。
实际上,依赖注入(DI)和直接使用new关键字创建对象在代码结构、可维护性和灵活性方面有着显著差异。以下是依赖注入的一些优势:
1. 降低耦合度:通过依赖注入,对象的创建和依赖关系由外部容器管理,减少了类之间的直接依赖,使得代码更加模块化,易于修改和扩展。
2.提高可测试性:依赖注入使得单元测试更加容易,因为可以更容易地替换依赖的对象。
3.灵活性和可配置性:依赖注入允许在运行时动态地改变对象的依赖关系,提供了更高的灵活性和可配置性。
使用@Resource注解或new关键字创建对象的具体区别如下:
- @Resource注解:这是一种基于Java注解的依赖注入方式,通常与Spring框架结合使用。它允许通过属性名或类型来注入依赖,代码简洁,易于维护。
- new关键字:直接使用new关键字创建对象,代码简单,但容易导致代码间耦合,难以进行单元测试和代码重用。总之,依赖注入是一种更高级、更灵活的编程方式,有助于提高代码质量。
有同学在学习 Spring 框架中可能会问这样的问题,为什么通过依赖注入就可以降低代码间的耦合呢?我通过 new 生产对象不也可以吗,不就是一行代码的不同,一个是 @Resource 注入,一个是 new 创建,怎么就降低耦合了?
今天博主就带大家来一步步剖析这个问题
一、传统方式创建对象通常我们是这样创建对象的
WuliCar wuli = new WuliCar();
wuli.run();
第一天:二明想用一辆车,然后通过 new 搞了一辆五菱荣光,调用 run 方法开始使用,车子跑起来了,很高兴。
一个月后:二明公司赚钱了,不想开五菱了,想换辆宝马,接下来二明一顿操作:
BaomaCar baoma = new BaomaCar();
baoma.run();
很好,车子从五菱换成了宝马,跑起来了,很高兴。
半年后:二明公司赚大钱了,二明想搞辆直升机,接下来又一顿操作
ZhiShenJi zhi = new ZhiShenJi();
zhi.fly();
这次改动比较大,宝马换成直升机,run 换成了 fly。
看到这里先思考一下,不想往下看,这样做有什么问题吗?
思考时间到,我们接着往下看。
从代码看好像没多大问题,不就改了两行代码嘛,这有啥。你想想,如果你的代码中有 1000 个地方都是这么写的,你想把宝马换成直升机岂不是要改 1000 次,run 改成 fly 又要改 1000 次,晚上别想下班了。
二、接口编程经过上次一顿操作,二明加了好几天班才弄完,二明想想每天这么搞不得累死,不行,得想想办法。于是二明脑子一转了,一想就想到了。我定义好一些方法,大家都按照这个规则来,不就好了。
public interface vehicle {
// 定义一个交通工具接口,有一个 work 方法
void work();
}
宝马实现这个接口:
public class Baoma implements vehicle {
@Override
public void work() {
System.out.println("宝马跑起来");
}
}
飞机实现这个接口:
public class ZhiShenJi implements vehicle {
@Override
public void work() {
System.out.println("直升机飞起来");
}
}
经过上面改造后,后面二明想把宝马换成直升机的时候只需要修改 new 那块就可以了,省了很多时间
利用接口确实好一些了,但是问题还是没有解决。为了提高内聚性,专职类负责特定的事情,所以我们使用一个类作为工厂类,既能生产 Car 又能生产 ZhiShenJi
class VehicleFactory{
VehicleFactory(){}
public static Vehicle getInstance(String type){
Animal result = null;
if("car".equals(type)){
result = new Car();
}
if("zhishenji".equals(type)){
result = new ZhiShenJi();
}
return result;
}
}
如果有一次我想锻炼身体,想骑自行车了,那么很简单
class VehicleFactory{
VehicleFactory(){}
public static Vehicle getInstance(String type){
Animal result = null;
if("car".equals(type)){
result = new Car();
}
if("zhishenji".equals(type)){
result = new ZhiShenJi();
}
if("zixingche".equals(type)){
result = new ZiXingChe();
}
return result;
}
}
Vehicle vehicle = VehicleFactory.getInstance("zixingche");
vehicle.work();
这种方法把创建对象的过程交给了一个专业的类(Factory),我只需要告诉他我需要什么(参数),他就会返回给我正确的对象,只是解决了内聚性的问题,但是他并没有解决我的声明语句七零八落的散落在程序中,我还是需要去将参数从car替换为zixingche
后来二明想到一个更绝妙的主意.我在写程序的时候不告诉工厂我需要什么,等到运行的时候我再告诉工厂我需要什么,再利用反射技术给我生产出来不就可以了吗?二明说干就干
Vehicle vehicle = VehicleFactory.getInstance(读取配置文件);
vehicle.work();
我想要的:zixingche
zixingche.work();
大功告成,这样我要什么,都写在一个配置文件中,利用反射技术就可以创建好,这样我就不用在生产了,下次换车的时候直接去配置文件中修改就好了,代码中不用修改。
对于生产对象这件和业务没有直接关系的事情,我们已经提取给了专业的工厂,专业的工厂还是根据配置文件进行的生产,想生产什么我只需要改一处即可,这就是降低了耦合性(生产对象和业务之间的耦合,让生产对象对业务的影响降到了最低)。
五、Spring IOC上面第四点说的那些功能,Spring IOC 已经帮助我们实现了,Spring IOC 就是利用工厂模式+反射实现自动生产对象,管理对象生命周期的功能。降低了代码的耦合
总结- 依赖注入的意思是你需要的东西不是由你创建的,而是第三方,或者说容器提供给你的。这样的设计符合正交性,即所谓的松耦合。
- 依赖注入是调用者仅通过声明某个组件就可以获得组件的控制权,而对该组件的依赖关系管理、查找、加载由外部完成。
- 依赖注入就是你不用关心对象的生命周期,什么时候被创建,什么时候销毁,只需直接使用即可,对象的生命周期由提供依赖注入的框架来管理。

