0%

最小化Ioc容器使用样例

最小化Ioc容器使用样例

什么是容器?容器是一种为某种特定组件的运行提供必要支持的一个软件环境。例如,Tomcat就是一个Servlet容器,它可以为Servlet的运行提供运行环境。类似Docker这样的软件也是一个容器,它提供了必要的Linux环境以便运行一个特定的Linux进程。IoC容器,可以管理所有轻量级的JavaBean组件,提供的底层服务包括组件的生命周期管理、配置和组装服务、AOP支持,以及建立在AOP基础上的声明式事务服务等。我们平时接触最多的就是Spring Framework,此篇中还会展示另外一个IoC容器google guice的使用例子。

原始样例

先创建一个空的maven工程。

1
2
3
4
5
6
7
8
package org.chaos;

public class Main {
public static void main(String[] args) {
BusinessService businessService = new BusinessService();
System.out.println(businessService.doBusiness("chaos"));
}
}
1
2
3
4
5
6
7
8
9
package org.chaos;

public class BusinessService {

public String doBusiness(String name) {
PrintService printService = new PrintService();
return "I need do print with " + printService.print(name);
}
}
1
2
3
4
5
6
7
package org.chaos;

public class PrintService {
public String print(String name) {
return "English print with " + name;
}
}

这里BusinessService直接强依赖于PrintService,如果使用者(这里是Main)根据特定条件来打印内容,就会遇到问题。例如

1
2
3
4
5
if (currentLocation.equals("中国")) {
//希望调用doBusiness然后执行中文打印
} else {
//希望调用doBusiness然后执行英文打印
}

这里就需要用到控制反转,肯定的是这里也不能使用具体的实现类了,不然我们需要根据具体的实现类编写多个doBusiness, 这也是IoC容器的基本功能体现。(常规做法实际上是先将new改为工厂类,从直接依赖接耦为间接依赖)

Spring实现模式

pom.xml添加依赖

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.17</version>
</dependency>
</dependencies>

加入beans.xml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

<bean id="businessService" class="org.chaos.BusinessService">
<constructor-arg ref="englishPrinterService"/>
</bean>

<bean id="englishPrinterService" class="org.chaos.EnglishPrintServiceImpl">
</bean>

</beans>
1
2
3
4
5
6
7
8
9
10
11
public class BusinessService {
private PrintService printService;

public BusinessService(PrintService printService) {
this.printService = printService;
}

public String doBusiness(String name) {
return "I need do print with " + printService.print(name);
}
}
1
2
3
4
5
public class EnglishPrintServiceImpl implements PrintService {
public String print(String name) {
return "English print with " + name;
}
}
1
2
3
public interface PrintService {
String print(String name);
}
1
2
3
4
5
6
7
8
9
10
public class Main {
public static void main(String[] args) {
ClassPathResource res = new ClassPathResource("beans.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
BusinessService businessService = (BusinessService) factory.getBean("businessService");
System.out.println(businessService.doBusiness("chaos"));
}
}

这里依赖关系存在于了beans.xml的管控中,BusinessService只与PrintService接口有耦合关系了。

Guice实现模式

pom.xml

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import com.google.inject.Inject;

public class BusinessService {
private final PrintService printService;

@Inject
public BusinessService(PrintService printService) {
this.printService = printService;
}

public String doBusiness(String name) {
return "I need do print with " + printService.print(name);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

public class Main {
static class PrinterModule extends AbstractModule {
@Override
protected void configure() {
bind(PrintService.class).to(EnglishPrintServiceImpl.class);
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new PrinterModule());
BusinessService businessService = injector.getInstance(BusinessService.class);
System.out.println(businessService.doBusiness("chaos"));
}
}

其实这里可以看出来Guice这一套有点类似最新SpringJava配置方式

参考

廖雪峰-IoC容器

Using JSR 330 standard annotations