tags: Spring


前言

在Spring的第二篇中主要讲解了Spring Core模块的使用IOC容器创建对象的问题,Spring Core模块主要是解决对象的创建和对象之间的依赖关系,因此本博文主要讲解如何使用IOC容器来解决对象之间的依赖关系

回顾以前对象依赖

我们来看一下我们以前关于对象依赖,是怎么的历程

直接new对象

  • 在最开始,我们是直接new对象给serice的userDao属性赋值...

class  UserService{UserDao userDao = new UserDao();
}复制代码

写DaoFactory,用字符串来维护依赖关系

  • 后来,我们发现service层紧紧耦合了dao层。我们就写了DaoFactory,在service层只要通过字符串就能够创建对应的dao层的对象了。

  • DaoFactory


public class DaoFactory {private static final DaoFactory factory = new DaoFactory();private DaoFactory(){}public static DaoFactory getInstance(){return factory;}public <T> T createDao(String className,Class<T> clazz){try{T t = (T) Class.forName(className).newInstance();return t;}catch (Exception e) {throw new RuntimeException(e);}}}复制代码
  • serivce
    private CategoryDao categoryDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.CategoryDAOImpl", CategoryDao.class);private BookDao bookDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.BookDaoImpl", BookDao.class);private UserDao userDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.UserDaoImpl", UserDao.class);private OrderDao orderDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.OrderDaoImpl", OrderDao.class);复制代码

DaoFactory读取配置文件

  • 再后来,我们发现要修改Dao的实现类,还是得修改service层的源代码呀..于是我们就在DaoFactory中读取关于daoImpl的配置文件,根据配置文件来创建对象,这样一来,创建的是哪个daoImpl对service层就是透明的

  • DaoFactory

public class DaoFactory {private  UserDao userdao = null;private DaoFactory(){try{InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");Properties prop = new Properties();prop.load(in);String daoClassName = prop.getProperty("userdao");userdao = (UserDao)Class.forName(daoClassName).newInstance();}catch (Exception e) {throw new RuntimeException(e);}}private static final DaoFactory instance = new DaoFactory();public static DaoFactory getInstance(){return instance;}public UserDao createUserDao(){return userdao;}}复制代码
  • service
    UserDao dao = DaoFactory.getInstance().createUserDao();
复制代码

Spring依赖注入

通过上面的历程,我们可以清晰地发现:对象之间的依赖关系,其实就是给对象上的属性赋值!因为对象上有其他对象的变量,因此存在了依赖...

Spring提供了好几种的方式来给属性赋值

  • 1) 通过构造函数
  • 2) 通过set方法给属性注入值
    1. p名称空间
  • 4)自动装配(了解)
  • 5) 注解

搭建测试环境

  • UserService中使用userDao变量来维护与Dao层之间的依赖关系

  • UserAction中使用userService变量来维护与Service层之间的依赖关系

  • userDao

public class UserDao {public void save() {System.out.println("DB:保存用户");}
}复制代码
  • userService

public class UserService {private UserDao userDao; public void save() {userDao.save();}
}复制代码
  • userAnction
public class UserAction {private UserService userService;public String execute() {userService.save();return null;}
}
复制代码

构造函数给属性赋值

其实我们在讲解创建带参数的构造函数的时候已经讲过了...我们还是来回顾一下呗..

我们测试service和dao的依赖关系就好了....在serice中加入一个构造函数,参数就是userDao

    public UserService(UserDao userDao) {this.userDao = userDao;//看看有没有拿到userDaoSystem.out.println(userDao);}复制代码

applicationContext.xml配置文件

<!--创建userDao对象--><bean id="userDao" class="UserDao"/><!--创建userService对象--><bean id="userService" class="UserService"><!--要想在userService层中能够引用到userDao,就必须先创建userDao对象--><constructor-arg index="0" name="userDao" type="UserDao" ref="userDao"></constructor-arg></bean>复制代码
  • 测试:可以成功获取到userDao对象
// 创建容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");//得到service对象UserService userService = (UserService) ac.getBean("userService");
复制代码

通过set方法给属性注入值

我们这里也是测试service和dao层的依赖关系就好了...在service层通过set方法来把userDao注入到UserService中

  • 为UserService添加set方法

public class UserService {private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;//看看有没有拿到userDaoSystem.out.println(userDao);}public void save() {userDao.save();}
}复制代码

applicationContext.xml配置文件:通过property节点来给属性赋值

  • 引用类型使用ref属性
  • 基本类型使用value属性
<!--创建userDao对象--><bean id="userDao" class="UserDao"/><!--创建userService对象--><bean id="userService" class="UserService"><property name="userDao" ref="userDao"/></bean>复制代码
  • 测试:

内部Bean

我们刚才是先创建userDao对象,再由userService对userDao对象进行引用...我们还有另一种思维:先创建userService,发现userService需要userDao的属性,再创建userDao...我们来看看这种思维方式是怎么配置的:

applicationContext.xml配置文件:property节点内置bean节点

<!--1.创建userService,看到有userDao这个属性2.而userDao这个属性又是一个对象3.在property属性下又内置了一个bean4.创建userDao--><bean id="userService" class="UserService"><property name="userDao"><bean id="userDao" class="UserDao"/></property></bean>复制代码
  • 测试

我们发现这种思维方式和服务器访问的执行顺序是一样的,但是如果userDao要多次被其他service使用的话,就要多次配置了...

p 名称空间注入属性值

p名称控件这种方式其实就是set方法的一种优化,优化了配置而已...p名称空间这个内容需要在Spring3版本以上才能使用...我们来看看:

applicationContext.xml配置文件:使用p名称空间

<bean id="userDao" class="UserDao"/><!--不用写property节点了,直接使用p名称空间--><bean id="userService" class="UserService" p:userDao-ref="userDao"/>复制代码
  • 测试

自动装配

Spring还提供了自动装配的功能,能够非常简化我们的配置

自动装载默认是不打开的,自动装配常用的可分为两种:

  • 根据名字来装配
  • 根据类型类装配

XML配置根据名字

applicationContext.xml配置文件:使用自动装配,根据名字

<bean id="userDao" class="UserDao"/><!--1.通过名字来自动装配2.发现userService中有个叫userDao的属性3.看看IOC容器中没有叫userDao的对象4.如果有,就装配进去--><bean id="userService" class="UserService" autowire="byName"/>复制代码
  • 测试

XML配置根据类型

applicationContext.xml配置文件:使用自动装配,根据类型

值得注意的是:如果使用了根据类型来自动装配,那么在IOC容器中只能有一个这样的类型,否则就会报错!

<bean id="userDao" class="UserDao"/><!--1.通过名字来自动装配2.发现userService中有个叫userDao的属性3.看看IOC容器UserDao类型的对象4.如果有,就装配进去--><bean id="userService" class="UserService" autowire="byType"/>复制代码
  • 测试:

我们这只是测试两个对象之间的依赖关系,如果我们有很多对象,我们也可以使用默认自动分配


###使用注解来实现自动装配###

@Autowired注解来实现自动装配:

  • 可以在构造器上修饰
  • 也可以在setter方法上修饰
  • 来自java的@Inject的和@AutoWired有相同的功能

如果没有匹配到bean,又为了避免异常的出现,我们可以使用required属性上设置为false。【谨慎对待】

  • 测试代码
@Component
public class UserService {private UserDao userDao ;@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}
}
复制代码

顺利拿到userDao的引用

注解

自从jdk5有了注解这个新特性,我们可以看到Struts2框架、Hibernate框架都支持使用注解来配置信息...

通过注解来配置信息就是为了简化IOC容器的配置,注解可以把对象添加到IOC容器中、处理对象依赖关系,我们来看看怎么用吧:

使用注解步骤:

  • 1)先引入context名称空间

    •   xmlns:context="http://www.springframework.org/schema/context"
      复制代码
  • 2)开启注解扫描器
    •   `<context:component-scan base-package=""></context:component-scan>`
      复制代码
    • 第二种方法:也可以通过自定义扫描类以@CompoentScan修饰来扫描IOC容器的bean对象。。如下代码:

//表明该类是配置类
@Configuration//启动扫描器,扫描bb包下的//也可以指定多个基础包//也可以指定类型
@ComponentScan("bb")
public class AnnotationScan {}
复制代码

在使用@ComponentScan()这个注解的时候,在测试类上需要@ContextConfiguration这个注解来加载配置类...

  • @ContextConfiguration这个注解又在Spring的test包下..

创建对象以及处理对象依赖关系,相关的注解:

  • @ComponentScan扫描器
  • @Configuration表明该类是配置类
  • @Component 指定把一个对象加入IOC容器--->@Name也可以实现相同的效果【一般少用】
  • @Repository 作用同@Component; 在持久层使用
  • @Service 作用同@Component; 在业务逻辑层使用
  • @Controller 作用同@Component; 在控制层使用
  • @Resource 依赖关系
    • 如果@Resource不指定值,那么就根据类型来找,相同的类型在IOC容器中不能有两个
    • 如果@Resource指定了值,那么就根据名字来找

测试代码

  • UserDao
package aa;import org.springframework.stereotype.Repository;/*** Created by ozc on 2017/5/10.*///把对象添加到容器中,首字母会小写
@Repository
public class UserDao {public void save() {System.out.println("DB:保存用户");}}复制代码
  • userService

package aa;import org.springframework.stereotype.Service;import javax.annotation.Resource;//把UserService对象添加到IOC容器中,首字母会小写
@Service
public class UserService {//如果@Resource不指定值,那么就根据类型来找--->UserDao....当然了,IOC容器不能有两个UserDao类型的对象//@Resource//如果指定了值,那么Spring就在IOC容器找有没有id为userDao的对象。@Resource(name = "userDao")private UserDao userDao;public void save() {userDao.save();}
}复制代码
  • userAction

package aa;import org.springframework.stereotype.Controller;import javax.annotation.Resource;/*** Created by ozc on 2017/5/10.*///把对象添加到IOC容器中,首字母会小写
@Controller
public class UserAction {@Resource(name = "userService")private UserService userService;public String execute() {userService.save();return null;}
}复制代码
  • 测试

package aa;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** Created by ozc on 2017/5/10.*/
public class App {public static void main(String[] args) {// 创建容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("aa/applicationContext.xml");UserAction userAction = (UserAction) ac.getBean("userAction");userAction.execute();}
}复制代码

注解和XML配置是可以混合使用的...


如果您觉得这篇文章帮助到了您,可以给作者一点鼓励

Spring第三篇【Core模块之对象依赖】相关推荐

  1. spring源码构建以及模块划分和依赖

    目录 Spring源码构建 环境环境 安装Gradle 编译源码 spring中的依赖关系 spring中的版本号规则 语义化版本命名通行规则 Spring版本命名规则 Spring源码构建 环境环境 ...

  2. Spring 事务core 模块-JdbcTeamplate 对象

    JdbcTeamplate 对象,其结构如下:

  3. .net程序员转战android第三篇---登录模块之静态登录

    这一篇我将分2个部分记录登录界面,第一部分是静态登录, 这部分将如何从界面布局.控件使用.文件关系.数据验证.登陆实现等5小块记录. 第二部分是动态登录,这块会基于上面的4小块,在数据验证不是静态数据 ...

  4. 初学Java ssh之Spring 第三篇

    在这篇中,我学习了依赖注入的两种方式:设值注入和构造注入. 在我们以前的思维中,如果调用一个类时,我们都需要将其手动实例化,当我们创建被调用的工作不需要我们完成时,这就是控制反转,当这个将被调用的实例 ...

  5. Python之路(第三篇) 模块

    模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...

  6. 【Spring第三篇】什么是Bean?

    在Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为bean.bean是一个由Spring IoC容器实例化.组装和管理的对象. 我们总结如下: 1.bean是对象,一个或者 ...

  7. 【C++从入门到踹门】第三篇:类和对象(中)类的默认成员函数

    目录 1.类的默认成员函数 2.构造函数 2.1 构造函数引入 2.2 构造函数概念及特点 3. 析构函数 3.1 析构函数引入 3.2 析构函数的概念 3.3 在哪些情况下会程序会执行析构函数? 3 ...

  8. 【c++师傅领进门,修行靠个人】第三篇:类和对象

    教你如何new一个对象 1 别急,先来了解你的对象 2 类之初体验 2.1 类的访问限定符 2.2 认识封装 2.3 类的作用域 3 来了,请创建你的对象 4.类对象模型 5 this指针 什么?你告 ...

  9. Spring基础配置篇(一)

    一.说在前面 怎样的架构的程序,我们认为是一个优秀的架构? 我们考虑的标准:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:就是可以做到,不断的增加代码,但是可以不修改原来的代码的程序. 如何 ...

最新文章

  1. wince中的hook(钩子)用法
  2. UML 类之间的几种关系
  3. Git 中 SSH key 生成步骤
  4. zabbix cpu核数 windows_Zabbix的应用(6)----常见错误
  5. java模拟单链表环形链表解决约瑟夫问题
  6. 学习总结——Selenium元素定位
  7. jq实现前端文件上传
  8. (26)ESLint一JS代码格式校验
  9. 面向对象之: 类空间问题及类之间的关系
  10. 如何搭建VUE环境?
  11. 分裂对象模型和TclCL(2)
  12. Nginx反向代理实现负载均衡web集群
  13. IS-IS详解(十六)——IS-IS 分片扩展
  14. jquery的快捷手册
  15. cakephp helper ajax,在JS Helper CakePHP中手动触发事件
  16. 关闭惠普计算机通电启动注册表,惠普电脑关机后自动重启的解决办法
  17. 谨以此文纪念我的大学四年
  18. SpringBoot整合druid数据源,quartz定式框架
  19. Banner(轮播)
  20. Javascript函数内静态变量与实例变量

热门文章

  1. mysql dump 数据时间_使用mysqldump备份数据及做时间点还原测试步骤
  2. diy机器人图片 手绘纸箱_废物利用,她用几个纸箱让家里变成动物园,孩子回家乐坏了!收藏...
  3. JAVA怎么实现网页退出系统_java后台实现js关闭本页面,父页面指定跳转或刷新操作...
  4. html5 css 三角形,css怎么画三角形?
  5. 隐藏功能_IOS 14.2 隐藏功能
  6. 站怎么点都是一样_抖音怎么做?这几样一样都不能少,你都做到了吗?
  7. github流程图_逆天插件,VSCode里也能画流程图了?Visio可以淘汰了?
  8. 自定义日历控android,Android 一个日历控件的实现小记
  9. 安装杀毒软件是保障计算机安全,安装杀毒软件是保障计算机安全的唯一措施
  10. 血型遗传关系c语言编程,根据血型遗传关系,编程实现:○1.输入