Spring第三篇【Core模块之对象依赖】


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配置是可以混合使用的...


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/539592.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring框架结构介绍

Spring提供了一站式解决方案&#xff1a; 1&#xff09; Spring Core spring的核心功能&#xff1a; IOC容器, 解决对象创建及依赖关系 2&#xff09; Spring Web Spring对web模块的支持。 -->可以与struts整合,让struts的action创建交给spring -->spring mvc模式 3…

java通过J2C获取用户名密码_WAS服务器上的J2C别名有什么用途?

这是我LdapTemplate类 公共LdapTemplate getLdapTemplete(字符串ldapID) {WAS服务器上的J2C别名有什么用途&#xff1f;if (ldapID.equalsIgnoreCase(Constants.LDAP1)){if (ldapTemplate1 null){try{PasswordCredential passwordCredential j2cAliasUtility.getAliasDetails…

百度坐标转换API使用

http://api.map.baidu.com/geoconv/v1/?coords121.54759,29.870724&from1&to5&aksGSOaO07WkRHHiCRxxbSQVBn 前提&#xff1a;121.54759,29.870724 是由手机硬件或谷歌地图获取的 错误的方法一&#xff1a; function standard2china(lng,lat){//http://api.map.ba…

Java语言所有异常类均继承自_Java将运行错误分为两类:(__)和(__), 其对应的类均派生自(__)类;...

【单选题】设 x,y 均为已定义的类名,下列声明对象x1的语句中正确的是( )【判断题】构造函数的方法名可以由编程人员任意命名。【单选题】能够实现对原文的鉴别和不可否认性的认证技术是( )。【单选题】设有定义语句int a[]{66,88,99}; 则以下对此语句的叙述错误的是( )。【判断…

Quartz业务类无法注入Spring对象问题

tags: 解决错误, titile: Quartz业务类无法注入Spring对象问题 Quartz业务类无法注入Spring对象问题 在刚开始遇到的时候还以为是Spring配置哪里错误了&#xff0c;结果搞了那么久&#xff0c;才知道Quartz与Spring注入对象是不关联的。。 因为Quartz的业务Job对象是由Quartz来…

如何解决ajax跨域问题

原文&#xff1a;http://www.congmo.net/blog/2012/06/27/ajax-cross-domain/ 跨域问题 起 因是这样的&#xff0c;为了复用&#xff0c;减少重复开发&#xff0c;单独开发了一个用户权限管理系统&#xff0c;共其他系统获取认证与授权信息&#xff0c;暂且称之为A系统&#xf…

spring bean创建细节

1) 对象创建&#xff1a; 单例/多例 scope"singleton", 默认值&#xff0c;即默认是单例【service/dao/工具类】 scope"prototype", 多例&#xff1b;【Action对象】 2) 什么时候创建? scope"prototype" 在用到对象的时候&#xff0c…

发送邮件程序报错454 Authentication failed以及POP3和SMTP简介

一、发现问题 在测试邮件发送程序的时候&#xff0c;发送给自己的QQ邮箱&#xff0c;程序报错454 Authentication failed, please open smtp flag first。 二、解决问题 进入QQ邮箱——>设置——>账户——>POP3/IMAP/SMTP选择——>开启POP3/SMTP服务。 三、POP3和S…

MySQL数据库是非关系_MySQL(数据库)基础知识、关系型数据库yu非关系型数据库、连接认证...

什么是数据库&#xff1f;数据库(Database)&#xff1a;存储数据的仓库高效地存储和处理数据的介质(介质主要是两种&#xff1a;磁盘和内存)数据库系统&#xff1a;DBS(Database System)&#xff1a;是一种虚拟系统&#xff0c;将多种内容关联起来的称呼DBS DBMS DBDBMS&…

WPF 使用MahApps.Metro UI库

http://www.cnblogs.com/happyyftk/p/6904766.html 本文示例源码下载&#xff1a;MetroWPF 官方示例地址&#xff1a;http://mahapps.com/guides/quick-start.html 官方控件示例地址&#xff1a;http://mahapps.com/controls/ MahApps.Metro 项目源码&#xff1a;https://githu…

SpringIOC容器-创建对象

SpringIOC容器&#xff0c;是spring核心内容。功能&#xff1a;创建对象&#xff0c;处理对象的依赖关系 IOC容器创建对象&#xff1a; 创建对象, 有几种方式&#xff1a; 1&#xff09; 调用无参数构造器 2&#xff09; 带参数构造器 3&#xff09; 工厂创建对象 工厂类&…

java注释搞笑图案_搞笑的代码注释,那些有趣的程序员

发表于 2019-04-24 16:11:26 by 月小升搞笑/**** .::::.* .::::::::.* ::::::::::: F*CK YOU* ..:::::::::::* ::::::::::::* .::::::::::* ::::::::::::::..* ..::::::::::::.* ::::::::::::::::* ::::::::::::: .:::.* :::: ::::: .::::::::.* .:::: :::: .:::::::::::.* .::…

SpringIOC容器-对象依赖

1 概述 Spring中&#xff0c;如何给对象的属性赋值? 【DI, 依赖注入】 1) 通过构造函数 2) 通过set方法给属性注入值 3) p名称空间 4) 自动装配 5) 注解 1.1 通过构造函数 <!-- ###############对象属性赋值############### --><!-- 1) 通过构造函数 --><be…

f5长连接策略

但是把这些短连接汇聚到一起&#xff0c;集中F5的设备上&#xff0c;通过F5与服务器建立平滑的长连接&#xff0c;就解决了不断增大的并发连接。比如说前台有15万个并发连接&#xff0c;经过F5的优化&#xff0c;在服务器上只有不到5000个并发连接&#xff0c;而且在此过程中&a…

pdo-mysql_PHP: MySQL (PDO) - Manual

PDO::MYSQL_ATTR_USE_BUFFERED_QUERY(int)Если этот атрибут установлен в true вPDOStatement, MySQL-драйвербудет использовать буферизованные версии API MySQL.Если вы пишете пе…

Spring IOC容器【p名称空间注入属性值 】

# p 名称空间给对象的属性注入值(spring3.0以上版本才支持) 需要引入&#xff1a; xmlns:p"http://www.springframework.org/schema/p" 举例 applicationContext.xml <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http…

Spring properties定义bean

2019独角兽企业重金招聘Python工程师标准>>> Spring提供了丰富的标签和注解来进行bean的定义&#xff0c;除此之外框架来提供了扩展机制让使用可以通过properties来定义bean&#xff0c;与强大的标签式和注解式的bean定义相比&#xff0c;properties提供的规则要简单…

Spring IOC容器-自动装配

1 autowire"byName" 根据名称自动装配&#xff0c;自动去IOC容器中找与属性名同名的引用的对象&#xff0c;并自动注入。 <!-- ###############自动装配############### --> <bean id"userDao" class"d_auto.UserDao"></bean&g…

linux下C++遍历文件夹下的全部文件;Windows/Linux下C++批量修改文件名,批量删除文件...

Linux下 C遍历目录下所有文件 1 rename(image_path.c_str(), image_path_new.c_str()); 2 remove(image_path_move.c_str()); 上述批量操作的代码是在linux下的参数设置&#xff1a; rename的参数&#xff0c;image_path为原文件的路径文件名&#xff0c;image_path_new为文件…

mongodb java 单例_Java单例MongoDB工具类

我经常对MongoDB进行一些基础操作&#xff0c;将这些常用操作合并到一个工具类中&#xff0c;方便自己开发使用。没用Spring Data、Morphia等框架是为了减少学习、维护成本&#xff0c;另外自己直接JDBC方式的话可以更灵活&#xff0c;为自己以后的积累留一个脚印。Java驱动版本…