系统架构——依赖注入

依赖注入DI(Dependency injection),通常是将对象的生命周期交给第三方的实现来管理,而不是在程序中硬编码。依赖注入解决的是对象谁来new的问题,依赖注入的实现都有一个IOC容器(Inversion of Control),用于管理对象的生命周期。程序语言都支持局部变量,或是静态的全局变量,这两种变量类型定义位置,决定了它们的生存周期,局部变量可能在代码快执行完就销毁了,如果这个代码块不停地重复执行,那这个变量就不停地重新生成,为了提高效率就可能把它变成全局变量,但变成了全局变量也可能会产生问题,那就是这样的变量多到一定程度之后,其它的开发者并不知道有这样的定义,于是又重复地去定义,增加了没有必要的内存消耗,况且还有很多变量是不需要跟程序的生命周期一致的,在有必要的时候就要及时销毁它们,比如一些会话级别的变量,为了实现这样的效果就要增加不少代码维护量。IOC容器接管这些工作,它将对象的生存期分为多个级别,对象的生成与销毁并不需要程序员去直接控制,如果代码中需要用到哪个对象,通过DI的方式跟IOC容器要就是了,通常这个过程是自动的,IOC会根据配置或标注,在程度初始化的时候,自动地给你填充进去。

举个数据层的例子,通常先定义一个Dao,里边有几个方法返回数据库的记录,并转换成实体对象。一个Dao分为接口和实现两部分,这样的好处是为了降低偶合,使用代理的模式,弱化对实现代码的依赖。

先定义一个接口:

public interface AccountRepository  {
	Account findByUsername(String username);
}

实现部分的代码:

public class AccountRepositoryImpl implements AccountRepository {
    @Autowired
    private SessionFactory sessionFactory;
    
    private Session getSession()
    {
        return sessionFactory.getCurrentSession();
    }
	Account findByUsername(String username){
	    String hql="SELECT account from Account where name=?";
        Query query=getSession().createQuery(hql).setString(0, id);
        Account account= query.uniqueResult<Account>();
        return account;
	}
}

写个测试类,看看效果:

public class AccountRepositoryTest extends CommonTest {

	@Autowired
	AccountRepository repo;
	
	@Test
	public void findByName() {
	    var obj = repo.findByUsername("test");
	    Assertions.assertNotNull(obj);
	}
}

然后有一天发现,SpringData挺好用的。于是修改了一下接口,连方法实现部分都不要了:

public interface AccountRepository extends JpaRepository<Account, String> {
	Account findByUsername(String username);
}

测试代码不需要变动。

原文地址:https://www.cnblogs.com/icoolno1/p/12831567.html