DI的概念和实现原理—Spring系列介绍
DI和AOP是Spring中的两个核心概念,要学习DI和AOP,首先就需要了解清楚什么是DI,什么是AOP,这篇文章会讲解一下DI的概念和实现原理,不足之处忘大家指正。
在传统的编程中,某个类型的依赖对象通常都是由该类型的对象自己创建,比如在原始的三层架构中,当控制器需要一个服务对象的时候,通常都是在控制器中直接创建该服务对象,或者写得高大上一点,弄个工厂方法,将控制层和服务层解耦,我们来看如下代码:
UserRepository接口的实现类
public class UserRepositoryImpl implements UserRepository {
@Override
public User findByUserName(String userName) {
return null;
}
}
UserService接口的实现类
public class UserServiceImpl implements UserService {
private UserRepository userRepository = new UserRepositoryImpl();
@Override
public User login(String userName) {
return userRepository.findByUserName(userName);
}
}
这是传统三层架构的一个代码片段,我想大多在学习阶段都写过这样的代码,文艺范一点的可能不会直接new UserRepositoryImpl(),而是使用工厂方法代替。但是不管使用哪种方式,我们会发现,UserRepository的对象是由UserService来进行控制的。
上面的例子就好像过去的生活,你肚子饿了,你需要自己到餐馆去点菜,然后等半天才能吃到美食。但是现在呢,我们只需要在手机上打开APP并下单。你需要做的就是在家里玩一把游戏或者看会书,饭就给你送到手上了。那么我们写代码能不能也这样呢?当我们需要对象的时候不是自己去创建,而是下个单,让别人给我们自动放进来呢?这就需要用到依赖反转(DI)这个技术了。
我们来简单了解一下上面的例子,首先商家需要在这个APP发布信息,比如点餐的菜单,然后我们才能在APP上下单。那么在程序中如何做呢?首先我们也需要一个注册中心,也就是存放对象的容器,然后提供服务的对象都需要放到这个容器中。当我们需要某种类型的对象的时候,只需要告诉容器,容器就会自动将该类型的对象自己传递给你了。
在Spring中,BeanFactory就是这么一个容器,我们需要将我们的Bean都交给BeanFactory来管理。如何将Bean交给BeanFactory管理呢?这就是配置文件的作用。我们可以使用xml、注解或者是Java代码来配置,如:
<bean id="userRepository" class="cn.cqbdqn.ems.repositories.impl.UserRepositoryImpl"/>
也可以在交给Spring管理的时候告诉Spring你需要一些什么类型的对象,如:
<bean id="userService" class="cn.cqbdqn.ems.service.impl.UserServiceImpl">
<!-- userRepository属性需要提供setter -->
<property name="userRepository" ref="userRepository"/>
</bean>
这样Spring就知道你的对象需要一个什么类型的属性,在Spring创建该类型的对象的时候就会自动在容器中搜索该类型的对象,并自动注入到你的对象中。这样就完成了从自己创建并管理对象到对象自动注入的过程的转变,我们需要做的工作就是告诉Spring我们需要一个什么类型的对象,将该类型的对象自动注入哪个属性就可以了。当我们需要修改该类型的对象实现的时候,只需要告诉(修改Spring配置文件)Spring,而不用修改我们的代码。
启动Spring的测试代码:
@Test
public void test(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring.xml");
UserService userService = ctx.getBean("userService", UserService.class);
User user = userService.login("admin");
assertNull(user);//断言user对象为空
}
DI解决了什么问题呢?对象之间的耦合。在我们的系统中,如果两个对象耦合太紧,会造成代码难以测试,难以利用,难以理解。但是对象之间又需要有一定的耦合,完全没有耦合的代码什么也做不了。为了完成有实际意义的复杂功能,不同的类必须以适当的方式进行交互。通过DI,对象的关系由系统负责协调各对象的第三方组件在创建对象的时候进行设定。对象无需自行创建或管理它们的依赖关系。