博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring_ioc,DI
阅读量:6086 次
发布时间:2019-06-20

本文共 7561 字,大约阅读时间需要 25 分钟。

ioc简介:

什么是IOC呢?

IOC(Inversion of Control),中文意思就是控制反转,ioc并不是一种特定的编程语言,指的是一种编程思想,指的是将创建对象的操作权限交给容器(这里指的是spring容器),通过容器来创建对象和管理对象,简单来说就是将原先的控制权由程序本身转给容器(本篇主要指的是spring)

 依赖注入

依赖注入(Dependency Injection):依赖注入指的是在程序的运行过程中,当程序需要调用另一个对象协助时,不用在代码中创建对象并进行调用,而是将创建过程与调用过程交给外部的容器来管理(spring),由外部容器创建后传递给层序

为什么会有依赖注入的存在?

一个稍微复杂一点的程序,其组成的类基本都是两个或两个以上了,这些类组成应用程序完成相关的业务逻辑。每个对象负责管理与自己相互协作的对象的引用,一个对象可能会引用多个对象,这就会导致高度的耦合和代码的难以测试,编码的基本准则是“低耦合,高内聚”

耦合具有两面性:

1:紧密的耦合会导致代码难以测试,难以复用,难以理解

2:一个程序要想完成特定的功能,一定程度的耦合又是必须的,不同的类之间必须进行一定的交互

依赖注入:通过依赖注入,对象的依赖关系将由负责协调系统中各个对象的第三方组件在创建对象时设定,对象无需自行创建或管理它们之间的依赖关系,也就是依赖关系将被注入到它们的依赖关系中去

实现依赖注入的两种方式

# 基于xml配置文件的依赖注入

setter方法

以下的例子相当于在一个类中使用另一个类中的方法

1:创建一个UserDao接口

package com.doaoao.dao;public interface UserDao {    void addUser();}

2:创建UserDao接口的实现类

package com.doaoao.impl;import com.doaoao.dao.UserDao;public class UserDaoImpl implements UserDao {    @Override    public void addUser() {        System.out.println("添加用户");    }}

3:创建UserService接口

package com.doaoao.dao;public interface UserService {    void addUser();}

4:创建UserService的实现类(在Service中使用UserDao)

package com.doaoao.impl;import com.doaoao.dao.UserDao;import com.doaoao.dao.UserService;public class UserServiceImpl implements UserService {    private UserDao userDao;    @Override    public void addUser() {        // 注:之前如果想使用UserDao的对象时,必须先创建该对象,如下        // UserDao userDao = new UserDaoImpl()        // 使用spring 由spring为我们创建对象        userDao.addUser();  // 调用UserDaoImpl中的实现方法    }     // 要给UserDao添加getter和setter方法    public UserDao getUserDao() {        return userDao;    }   // spring容器在实现依赖注入时会调用set方法,将userDao对象注入给当前对象,也就是UserServiceImpl类的对象   public void setUserDao(UserDao userDao) { this.userDao = userDao; } }

5:修改配置文件中的内容(当Spring读取配置文件时,会将userDao注入到对应的类中)

     

6:添加测试类

@Test    public void Test02(){        // 读取spring配置文件        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        // 从配置文件中获取对应id所对应的对象        UserService userService = (UserService) context.getBean("userService");        userService.addUser();    }

# 使用spring的依赖注入之后,spring容器会帮我们创建UserDaoImpl的对象,并通过setter方法注入到UserService中的userDao属性上面

## 构造注入(容器通过构造方法将实例化的对象进行注入)

1:修改之前的UserServiceImpl,添加有参构造方法

package com.doaoao.impl;import com.doaoao.dao.UserDao;import com.doaoao.dao.UserService;public class UserServiceImpl implements UserService {    private UserDao userDao;    @Override    public void addUser() {        // 注:之前如果想使用UserDao的对象时,必须先创建该对象,如下        // UserDao userDao = new UserDaoImpl()        // 使用spring 由spring为我们创建对象        userDao.addUser();  // 调用UserDaoImpl中的实现方法    }    // 构造注入    public UserServiceImpl(UserDao userDao) {        this.userDao = userDao;    }}

 2:修改配置文件

 


 

## 基于注解的依赖注入

  @Controller -----> springmvc中的controller

  @Repository ----> dao层

  @Service ---------> service层

  @Component --->可以代替上方三个

使用依赖注入,我们九不必再applicationContext.xml中注册bean

1:在配置文件中添加文件扫描器(使用注解就得先加上文件扫描器,扫描对应的类)

2:在类上使用注解 @Component,该注解中的参数用于指定该类的id

package com.doaoao.impl;import com.doaoao.dao.UserDao;import org.springframework.stereotype.Repository;@Component("userDao")public class UserDaoImpl implements UserDao {    @Override    public void addUser() {        System.out.println("执行了addUser");    }}

 在spring中提供类与@Component等效的注解

  @Repository 用于对 DAO 实现类进行注解

  @Service 用于对 Service 实现类进行注解
  @Controller 用于对 Controller 实现类进行注解

 例如在dao层的 UserDaoImpl 中使用 @Repository 注解

package com.doaoao.impl;import com.doaoao.dao.UserDao;import org.springframework.stereotype.Repository;@Repository("userDao")public class UserDaoImpl implements UserDao {    @Override    public void addUser() {        System.out.println("执行了addUser");    }}

3:在service层的 UserServiceImpl 上使用 @Service

package com.doaoao.impl;import com.doaoao.dao.UserDao;import com.doaoao.dao.UserService;import org.springframework.stereotype.Service;@Service("userService")public class UserServiceImpl implements UserService {    private UserDao userDao;    @Override    public void addUser() {
// 使用spring 由spring为我们创建对象 userDao.addUser(); } // 构造注入 public UserServiceImpl(UserDao userDao) { this.userDao = userDao; }}

4:创建测试方法(与之前相同)

@Test    public void Test02(){        // 读取spring配置文件        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        // 从配置文件中获取对应id所对应的对象        UserService userService = (UserService) context.getBean("userService");        userService.addUser();    }

@Autowrite注解

加上该注解后,会按照类型进行装配,上面的示例中通过UserServiceImpl的构造方法对UserDao的注入,我们可以将这个构造方法省略,我们可以在private UserDao userDao上添加@Autowired注解,该注解默认使用按类型自动装配,即容器会查找UserDao类型的实例将其注入,spring容器会自动查找该对象

当使用@AUtowrite注解时,@Repository("userDao") 可以改写成 @Repository,因为默认是根据类型进行注入的,会自动找到该类型所对应的对象

我么可以对其进行修改,让其根据名称进行注入,还可以使用 @Qualifier注解让@Autowrite根据名称自动装配,

@Qualifier中的名称要跟UserDaoImpl类中@Repository("userDao")的名称一致,spring在查找对象时就会根据 userDao这个名字去查找

package com.doaoao.impl;import com.doaoao.dao.UserDao;import com.doaoao.dao.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;@Service("userService")public class UserServiceImpl implements UserService {    @Autowired    @Qualifier("userDao")    private UserDao userDao;    @Override    public void addUser() {        userDao.addUser();     }    // 无需构造方法    // public UserServiceImpl(UserDao userDao) {    //     this.userDao = userDao;    // }}

@Resource注解(该注解不是spring提供的,是java提供的注解)

该注解默认使用名字进行注解(来完成装配的/注入的)当我们下方没有写名字时,就是使用类型进行装配的(和 @Autowired)

可以按照名字进行装配 @Resource(name = “userDao”),当指定名字时,名字得和@Repository("userDao") 一样

@Service("userService")public class UserServiceImpl implements UserService {    @Resource    private UserDao userDao;        @Override    public void addUser() {        userDao.addUser();    }}

下面另一种写法利用类型进行bean的注入

@Service("userService")public class UserServiceImpl implements UserService {    @Resource(type = "userDao")    private UserDao userDao;        @Override    public void addUser() {        userDao.addUser();    }}

两个区别:@Autowired是spring提供的,@Resource是java提供的,这两种注解在实际开发中二选一即可

@Autowired默认根据类型进行装配,@Resource默认使用名字进行装配

 // 使用注解实现初始化和销毁操作

@PostConstructpublic void before() {    System.out.println("开始");}@PreDestroypublic void after() {    System.out.println("结束");}

 利用注解@Scope指定bean的作用域,默认的作用域为 singleton 单例模式

@Scope("prototype")@Repository("userDao")public class UserDaoImpl implements UserDao {    @Override    public void addUser() {        System.out.println("执行了方法 UserDaoImpl");    }}

## 注解和xml配置的利弊

注解的好处是,配置方便,直观。但其弊端也显而易见:以硬编码的方式写入到了 Java代码中,其修改是需要重新编译代码的。

XML 配置方式的最大好处是,对其所做修改,无需编译代码,只需重启服务器即可将新的配置加载。

若注解与 XML 同用,XML 的优先级要高于注解。这样做的好处是,需要对某个 Bean 做修改,只需修改配置文件即可。当然,此时,Bean 类要有 setter 或构造器。

## 如何添加多个配置文件

随着系统中的Bean的数量增加,会导致配置温江变得及其的臃肿,会导致可维护性的降低,为了避免这种事情的发生,可以将Spring配置文件分解成多个配置文件

# 添加多个配置文件-方式1

// 在resource目录下创建多个配置文件spring-app.xmlspring-bean.xml// 在测试方法中:将配置文件的文件名写道数组中,然后将该数组作为参数传入 ClassPathXmlApplicationContexString[] files = {"spring-aop.xml","spring-bean.xml","applicationContext.xml"};ApplicationContext context = new ClassPathXmlApplicationContext(files);

# 添加多个配置文件-方式2

选取一个主配置文件,例如选取 applicationContext.xml

在applicationContext.xml配置文件中加入如下的内容,这时就好比将 applicationContext.xml 配置文件变成一个父配置文件

 然后再测试代码中使用即可

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

...

本笔记参考自:小猴子老师教程 http://www.monkey1024.com

转载于:https://www.cnblogs.com/Doaoao/p/10740366.html

你可能感兴趣的文章
Project:如何分析项目中的资源分配情况
查看>>
HDU 4803 Poor Warehouse Keeper (贪心+避开精度)
查看>>
小错误汇总
查看>>
Spring源码系列 — Envoriment组件
查看>>
java正则表达式去除html标签,Java中正则表达式去除html标签
查看>>
使用Cobbler批量部署Linux操作系统
查看>>
zabbix企业应用之服务端与客户端的安装
查看>>
实例讲解遗传算法——基于遗传算法的自动组卷系统【理论篇】
查看>>
无法在web服务器上启动调试。调试失败,因为没有启用集成windows身份验证
查看>>
Bat相关的项目应用
查看>>
Django为数据库的ORM写测试例(TestCase)
查看>>
web.xml中的contextConfigLocation在spring中的作用
查看>>
NYOJ-107 A Famous ICPC Team
查看>>
与众不同 windows phone (44) - 8.0 位置和地图
查看>>
Visual Studio Code 使用 ESLint 增强代码风格检查
查看>>
iOS设备中的推送(二):证书
查看>>
敏捷 - #3 原则:经常提供工作软件 ( #3 Agile - Principle)
查看>>
数据结构与算法:二分查找
查看>>
使用思科模拟器Packet Tracer与GNS3配置IPv6隧道
查看>>
Linux设备驱动之Ioctl控制【转】
查看>>