最小化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("中国")) { } else { }
|
这里就需要用到控制反转,肯定的是这里也不能使用具体的实现类了,不然我们需要根据具体的实现类编写多个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
这一套有点类似最新Spring
的Java
配置方式
参考
廖雪峰-IoC容器
Using JSR 330 standard annotations