您的位置 首页 java

Java开发大型互联网架构- spring架构依赖注入那些不知道的事

引言

控制反转(Inversion of Control,英文缩写为IoC)是框架的重要特征,并非面向对象编程的专用术语。它包括依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。

依赖注入

依赖注入听起来比较吓人,貌似一种非常复杂的编程技术或者设计模式。实际上依赖注入并不复杂,通过在工程中应用依赖注入技术,可以得到更简单、更容易理解和测试的代码。

How DI works

除了Hello-world级别的程序,稍微复杂一点的 Java 应用都需要多个类配合实现功能。一般而言,每个类自己负责获取它要合作的类对象的引用,这会导致代码高度耦合且难以测试。

首先看如下代码:

package com. Spring .sample.knights;

public class DamselRescuingKnight implements Knight {

private RescueDamsel quest quest;

public DamselRescuingKnight() {

this.quest = new RescueDamsel Quest (); //与RescueDamselQuest紧耦合

}

public void embarkOnQuest() {

quest.emark();

}

}

可以看出,DamselRescuingKnight在它的 构造函数 中创建了自己的Quest实例——RescueDamselQuest实例,这使得DamselRescuingKnight与RescueDamselQuest紧密耦合,如果需要刺杀Damsel,则这个刀可以使用,但是如果需要刺杀恐龙,则这个刀就派不上用场了。

更糟的是,给DamselRescuingKnight写单元测试很不方便,在这个测试中,你必须确认:当调用knight的emarkOnQuest函数时,quest的embark函数也正确调用,但这并不容易。

耦合是一头双头怪:一方面,紧耦合的代码难以测试、难以复用并且难以理解,并且经常陷入“修复一个bug但引入一个新的bug”的开发怪圈中;另一方面,应用程序必须存在适当的耦合,否则该应用无法完成任何功能。总之,耦合是必要的,但是应该控制组件之间的耦合程度。

通过使用依赖注入(DI)技术,对象之间的依赖关系由Spring框架提供的容器进行管理,而不需要某个对象主动创建自己需要的引用,如下图所示:

再看一个BraveKnight类的例子:

package com.spring.sample.knights;

public class BraveKnight implements Knight {

private Quest quest;

public BraveKnight(Quest quest) { // Quest实例被注入

this.quest = quest;

}

public void embarkOnQuest() {

quest.emark();

}

}

该对象不再局限于一种quest实例,在构造过程中利用构造函数的参数传入quest实例,这种类型的依赖注入称为构造注入。

还有一点需要注意,使用接口定义quest实例,这就是面向接口编程,使得BraveKnight不再局限于某种特定的Quest实现,这就是DI带来的最大的好处——松耦合。

实现依赖注入

在上述例子代码可以看出,Spring相当于将依赖注入的位置从BraveKnight类中剥离出来,那么具体的依赖注入代码如何写呢?开发人员如何规定给BraveKnight注入哪个Quest实现,例如SlayDragonQuest?

package com.spring.sample.knights;

import java.io.PrintStream;

public class SlayDragonQuest implements Quest {

private PrintStream stream;

public SlayDragonQuest(PrintStream stream) {

this.stream = stream;

}

public void emark() {

stream.println(“Embarking on quest to slay the dragon!”);

}

}

在Spirng框架中,最通用的方法是通过写XML配置文件来定义组件之间的依赖关系,如下所示:

<?xml version=”1.0″ encoding=”UTF-8″?>

<beans xmlns=””

xmlns:xsi=””

xsi:schemaLocation=” “>

<bean id=”knight” class=”com.spring.sample.knights.BraveKnight”>

<constructor-arg ref=”quest” />

</bean>

<bean id=”quest” class=”com.spring.sample.knights.SlayDragonQuest”>

<constructor-arg value=”#{T(System).out}” />

</bean>

</beans>

在这个xml配置文件中分别定义了BraveKnight和SlayDragonQuest两个bean:在BraveKnightbean的定义中,通过构造器函数传入一个SlayDragonQuest的引用;在SlayDragonQuest的定义中,通过SpEL语言将System.out传入它的构造函数。

Spring 3.0引入了JavaConfig,这种写法比xml文件的好处是具备类型安全检查,例如,上面XML配置文件可以这么写:

package com.spring.sample.knights.config;

import com.spring.sample.knights.BraveKnight;

import com.spring.sample.knights.Knight;

import com.spring.sample.knights.Quest;

import com.spring.sample.knights.SlayDragonQuest;

import org.springframework.context. annotation .Bean;

import org.springframework.context.annotation. Configuration ;

@Configuration

public class KnightConfig {

@Bean

public Knight knight() {

return new BraveKnight(quest());

}

@Bean

public Quest quest() {

return new SlayDragonQuest(System.out);

}

}

不论是基于XML的配置还是基于Java文件的配置,都由Spring框架负责管理beans之间的依赖关系。

启动依赖注入

在Spring应用中,由application context负责加载beans,并将这些beans根据配置文件编织在一起。Spring框架提供了几种application context的实现,如果使用XML格式的配置文件,则使用ClassPathXmlApplicationContext;如果使用Java文件形式的配置文件,则使用AnnotationConfigApplicationContext。

package com.spring.sample.knights;

import com.spring.sample.knights.config.KnightConfig;

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KnightMain {

public static void main(String[] args) {

// ClassPathXmlApplicationContext context =

// new ClassPathXmlApplicationContext(“classpath:/knight.xml”);

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(KnightConfig.class);

Knight knight = context.getBean(Knight.class);

knight.embarkOnQuest();

context.close();

}

}

上述代码中,根据KnightConfig.java文件创建Spring应用上下文,可以把该应用上下文看成对象工厂,来获取idknight的bean。

总结

以 上就是我对Java开发大型互联网架构- spring架构依赖注入那些不知道的事问题及其优化总结,分享给大家,觉得收获的话可以点个关注收藏转发一波喔,谢谢大佬们支持!

最后,每一位读到这里的网友,感谢你们能耐心地看完。希望在成为一名更优秀的Java程序员的道路上,我们可以一起学习、一起进步!都能赢取白富美,走向架构师的人生巅峰!

想了解学习Java方面的技术内容以及Java技术视频的内容可加群:722040762 验证码:头条(06 必过)欢迎大家的加入哟!

文章来源:智云一二三科技

文章标题:Java开发大型互联网架构- spring架构依赖注入那些不知道的事

文章地址:https://www.zhihuclub.com/179344.shtml

关于作者: 智云科技

热门文章

网站地图