栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring控制反转与依赖注入

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring控制反转与依赖注入

1)什么是控制反转

传统的编程思路是,当我需要某个对象时,我便自己去实例化调用它 。而控制反转则是,当我需要某个对象时,自然有人帮我们实例化它 。简单的来说,这是一种衣来张口,饭来伸手式的控制模式,这也符合spring最根本的使命--简化java开发 。

2)什么是依赖注入

依赖注入,即是SpringIOC的一种实现方式,在我们完成业务开发的过程中,需要引入的依赖,都由交由spring容器管理注入 。简单的说,就是由spring容器替我们实例化对象 。

3)依赖注入解决了什么问题

在传统的业务实现中,一个类是解决不了所有问题的,在一个类中我们通常会引入许多其它类来满足我们的业务需求,这个时候我们避免不了去实例化不同的对象,而面临需求变更时,相关的改动往往是牵一发而动全身,这时候我们希望有一种能让类与类之间的联系变得不那么密切的方式来修改我们的代码 。这也就是依赖注入给我们带来的最大收益--松耦合 。

4)依赖注入的实现

首先新建一个maven项目,引入spring核心依赖和其他相关依赖:



    4.0.0

    ice-maple
    ice.maple
    1.0-SNAPSHOT

    
        
        
        
            org.springframework
            spring-core
            4.3.11.RELEASE
        
        
            org.springframework
            spring-beans
            4.3.11.RELEASE
        
        
            org.springframework
            spring-context
            4.3.11.RELEASE
        
        
            junit
            junit
            4.12
        
        
        
            org.springframework
            spring-test
            4.3.11.RELEASE
        
    

假设我们的同事给我们提供了一个获取用户的接口,我们需要调用它进行显示,传统意义上我们可能需要这么做:

public class UserService implements IUserService {
    private IUserDao userDao = new UserDao();

    public List getUsers(){
       return userDao.getUsers();
    }
}

而测试的时候我们会这么做:

   @Test
    public void getUsers() {
//        ContextConfiguration contextConfiguration = new ContextConfiguration().locations("classpath:spring-config.xml");
        IUserService userService = new UserService();
        userService.getUsers().forEach(n -> {
            System.out.println(n.getName());
            System.out.println(n.getSex());
        });
    }

当我们采用这种方式完成业务,此时若有一个需求导致同事更换了实现类,那么在他新建类的同时,不论是测试还是我们的接口调用,都要做同步修改,由于我们在编写代码时类之间的紧密联系,导致我们可能在一个小小的业务改动上可能要进行多方的代码改动,而大多数时候这些类是多个不同的人写的,依赖注入能很好的解决我们这个问题 。

我们在resource下新建spring-config配置文件,并对service类进行修改:
spring-config.xml




    

    
        
            
        
    

    


UserService

public class UserService implements IUserService {
    private IUserDao userDao;

    public List getUsers(){
       return userDao.getUsers();
    }

    public IUserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }
}

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-config.xml")
//@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
    @Autowired
    UserService userService;

    @Test
    public void getUsers() {
        userService.getUsers().forEach(n -> {
            System.out.println(n.getName());
            System.out.println(n.getSex());
        });
    }
}

运行我们可能看到得到了想要的结果,说明注入成功:

当然我们也可以用构造方法的方式注入,service类增加构造方法并对配置文件做部分改动:

UserService

   public UserService(IUserDao userDao) {
        this.userDao = userDao;
    }

spring-config.xml

   
        
            
        
    

测试类不做改动,运行的效果是相同的 。

我们也可以不使用这种注册bean的方式,因为这种注册方式事实上并没有给我们简化代码,只是方便了我们的同意管理,我们可以换一种方式实现它,在dao和service上分别加上@Repository和@Service的注解,可以去掉构造方法和getter,setter方法,修改配置文件

spring-config.xml




    


UserService

@Service
public class UserService implements IUserService {
    @Autowired
    private IUserDao userDao;

    public List getUsers(){
       return userDao.getUsers();
    }
}

运行测试类,正常启动 。

当然我们也可以不需要配置文件,直接采用配置类的方式做这件事情

新建SpringConfig类

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("ice.maple")
public class SpringConfig  {

}

修改测试类:

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = "classpath:spring-config.xml")
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {

    @Autowired
    UserService userService;
    @Test
    public void getUsers() {
        userService.getUsers().forEach(n -> {
            System.out.println(n.getName());
            System.out.println(n.getSex());
        });
    }
} 

运行测试类,一切正常 。

接下来,我们看看如果spring扫描到了两个实现类会发生什么:

我们新建一个PersonDao并加上@Repository注解,启动测试类 。

运行发现并没有报错,spring选择了UserDao作为实现类,我们再修改一下UserDao的类名 。

再次运行发现,当实现类为两个类名与接口无关无关的类时,将会报错,原因是找到了两个不同的实现类 。这时候我们可以修改注解指定这个实现类:

@Repository("userDao") 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/925208.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号