文档章节

Spring应用学习——IOC

江左煤郎
 江左煤郎
发布于 2018/11/16 21:26
字数 3333
阅读 38
收藏 5

1. Spring简介

    1. Spring的出现是为了取代EJB(Enterprise JavaBean)的臃肿、低效、脱离现实的缺点。Spring致力于J2EE应用的各层(表现层、业务层、持久层)的解决方案,Spring是企业应用开发的“一站式”选择。

    2. 定义:Spring是分层的JavaSE/EE应用一站式的轻量级开源框架(官网: http://spring.io/ ),以Ioc(Inverse of control)控制反转和Aop(Aspect Oriented Programming)面向切面编程为核心。

    3. 优点:

  • 轻量级:针对EJB来说,使用方便。
  • 一站式:spring针对各各层(表现层、业务层、持久层)提出解决方案。
    • 表现层:springmvc(spring自己的mvc框架),提供和其它web框架整合方案。
    • 业务层:spring基于aop(面向切面编程)思想进行事务控制。
    • 持久层:spring自己提供JdbcTemplate,提供和其它持久层框架整合的方案。

    4. spring核心 :Ioc(控制反转)和aop(面向切面编程)。重点是:IOCspring要管理各各层的bean

    5. Spring模块组件图:

2. Spring IOC

1. 什么是IOC

    1. 不使用ioc,代码中创建一个对象直接操作接口实现类,并没有面向接口开发。面向接口开发指的是调用接口的方法,只面向接口而不面向接口实现类,因为一个接口可能有多个实现类。而没有面向接口开发的问题就是调用接口的类和接口实现类之间存在直接耦合。比如下列代码

//老板向一个写字员发出命令去做一个工作
public class Boss {
	private Writer emp;//直接使用Writer类,与Boss产生强依赖关系,直接耦合

	//老板只能向写字员发出命令,如果想要向一个秘书或其他员工发出命令则无法实现,这显然是不合理的
	public void order(){
		emp=new Writer();
		emp.doJob();
	}
}
public class Writer{
	public void doJob(){
		System.out.println("do something");
	}
}

面向接口开发的改进代码:

//老板向一个员工发出命令去做一个工作
public class Boss {
	private Employee emp;//使用Employee接口,将具体实现类与Boss解耦合,这样就大大增强了代码的可重用性并减弱耦合度

	//老板可以向任何一个实现了Employee接口的员工类发出命令
	public void order(){
		emp=new Writer();
		emp.doJob();
	}
}
public class Writer implements Employee{
	public void doJob(){
		System.out.println("do something");
	}
}
public interface Employee {
	public void doJob();
}

    2. IOC:Inverse of Control,即控制反转。是指将原来程序中自己创建实现类对象的控制权反转到IOC容器中。只需要通过IOC获了对象的实例,将IOC当成一个黑盒子、工厂。对象只与工厂耦合,对象之间没有耦合。而上面的代码也可以改为

//老板向一个员工发出命令去做一个工作
public class Boss {
	private Employee emp;//使用Employee接口,这样就大大增强了代码的可重用性并减弱耦合度
	//老板可以向任何一个实现了Employee接口的员工类发出命令,但这里的Employee的具体实现类对象由IOC容器提供,通过IOC容器来生成所需要的对象,这样可以将Boss类与具体员工类解耦,所有的类之间的依赖关系都由IOC容器进行管理,便于修改维护

	public void order(){
        emp=IOC容器.getEmp();
		emp.doJob();
	}
}
public class Writer implements Employee{
	public void doJob(){
		System.out.println("do something");
	}
}
public interface Employee {
	public void doJob();
}

2. Spring IOC的使用

    1. 首先建立一个Maven项目,通过Maven来导入所需要的jar包,主要是spring-webmvc.jar以及其相关的依赖jar包,使用4.3.版本,另外要注意,JDK版本与Spring版本的兼容问题,Spring4.0以后的版本建议使用JDK1.8版本;其次要导入commons-logging.jar,该包是Spring所使用的JCL日志体系jar包,只有相关接口,具体的实现类还需要导入log4j.jar。

    2. 编写Spring IOC容器的配置文件:是一个xml文件

  • 引入xml文件Spring的相关标签约束,加入的每一个Spring的相关jar包里都会包含该jar包相关的约束文件,具体如何添加可以网上搜索相关方法,这里给一个基本全面的标签约束,可以直接复制粘贴使用,xsi:schemaLocation中可以修改每个版本的约束文件,比如Spring4.3版本的beans相关约束可以将http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 改为 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    <beans xmlns="http://www.springframework.org/schema/beans" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context" 
    	xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    	xmlns:jee="http://www.springframework.org/schema/jee" 
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:aop="http://www.springframework.org/schema/aop" 
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xmlns:util="http://www.springframework.org/schema/util"
    	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
    		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
    		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
    		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
    		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">

     

  • 在xml文件中的beans标签内添加bean,bean标签内有多个属性以及一些嵌套标签,用于定义bean的相关操作,下面简单定义一个bean作为示例
    //注意,一个JavaBean类的规范实现
    public class UserData{
    	private String cn_user_id;
    	private String cn_user_name;
    	private String cn_user_password;
    	public static UserData getUser(){
    		return new UserData("9527","9527","9527");
    	}
    	public UserData(String cn_user_id, String cn_user_name, String cn_user_password) {
    		super();
    		this.cn_user_id = cn_user_id;
    		this.cn_user_name = cn_user_name;
    		this.cn_user_password = cn_user_password;
    	}
    //IOC容器中的bean必须有无参构造方法,也就是默认构造方法
    	public UserData() {
    		super();
    	}
    	public String getCn_user_id() {
    		return cn_user_id;
    	}
    	public void setCn_user_id(String cn_user_id) {
    		this.cn_user_id = cn_user_id;
    	}
    	public String getCn_user_name() {
    		return cn_user_name;
    	}
    	public void setCn_user_name(String cn_user_name) {
    		this.cn_user_name = cn_user_name;
    	}
    	public String getCn_user_password() {
    		return cn_user_password;
    	}
    	public void setCn_user_password(String cn_user_password) {
    		this.cn_user_password = cn_user_password;
    	}
    	
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" 
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    	<!-- bean标签:
    		1.id/name属性:用来标示bean的名称,该名称在SpringIOC容器中不允许重复,如果不指定名称,将默认为类路径
    		2.class属性:IOC要管理实现类的全限定路径名,IOC将根据此路径去实例化类对象
    	 -->
    	<bean id="user" class="com.cloud_note.entity.UserData"></bean>
    	<!-- SpringIOC实例化bean的三种方法:
    	1.默认无参构造器
    	2.有参构造器
    	3.静态工厂方法
    	 -->
    	<!-- 有参构造器方法 -->
    	<bean id="user1" class="com.cloud_note.entity.UserData">
    	<!-- index指参数在参数列表的下标,从0开始 -->
    		<constructor-arg index="0" value="9527" type="java.lang.String"></constructor-arg>
    		<constructor-arg index="1" value="9527" type="java.lang.String"></constructor-arg>
    		<constructor-arg index="2" value="9527" type="java.lang.String"></constructor-arg>
    	</bean>
    	<!-- 静态工厂方法,通过类中的静态工厂方法生成bean实例 -->
    	<bean id="user2" class="com.cloud_note.entity.UserData" factory-method="getUser">
    
    	<!-- bean作用域:
    	1.singleton:单例模式,即在Spring容器启动时只生成一个bean实例,在每次访问(getBean)时都将此对象返回,Spring容器默认此方式
    	2.prototype:多例模式,即每次访问(getBean)Spring容器都会返回一个新实例
    	3.request
    	4.session
    	 -->
    	<bean id="user" class="com.cloud_note.entity.UserData" scope="singleton"></bean>
    	<bean id="user1" class="com.cloud_note.entity.UserData" scope="prototype"></bean>
    	</bean>
    </beans>

  • 编写测试代码,测试是否能从上面配置的IOC容器中取出指定的bean对象
    //测试从Spring中获取bean实例,该测试方法需要导入junit的jar包,来使用@Test相关注解
    public class TestCase1 {
    	//测试无参构造器方法
    	@Test
    	public void test1(){
    		//1.获取SpringIOC容器对象
    		ApplicationContext app=new ClassPathXmlApplicationContext("config/applicationContext.xml");
    		//2.从SpringIOC中获取对应的bean实例
    		UserData user=(UserData) app.getBean("user");
    		System.out.println("获取成功");
    	}
    	//测试有参构造器方法
    	@Test
    	public void test2(){
    		ApplicationContext app=new ClassPathXmlApplicationContext("config/applicationContext.xml");
    		UserData user=(UserData) app.getBean("user1");
    		System.out.println(user.getCn_user_id());
    	}
    	//测试静态工厂方法
    	@Test
    	public void test3(){
    		ApplicationContext app=new ClassPathXmlApplicationContext("config/applicationContext.xml");
    		UserData user=(UserData) app.getBean("user2");
    		System.out.println(user.getCn_user_id());
    	}
    	
    	//获取SpringIOC容器对象的方法
    	@Test
    	public void test4(){
    		//1.FileSystemXmlApplicationContext是通过加载文件系统路径下的配置文件来创建一个容器实例
    		ApplicationContext app1=new FileSystemXmlApplicationContext("/src/main/resources/config/applicationContext.xml");
    		//2.ClassPathXmlApplicationContext是通过加载classpath路径下的配置文件来创建一个容器实例
    		ApplicationContext app2=new ClassPathXmlApplicationContext("config/applicationContext.xml");
    		//3.同时加载多个配置文件,可以连续填写多个路径参数或传入数组,或者通过通配符来加载
    		ApplicationContext app3=new ClassPathXmlApplicationContext("config/applicationContext.xml","config/applicationContext1.xml");
    		String[] configs=new String[]{"config/applicationContext.xml","config/applicationContext1.xml"};
    		ApplicationContext app4=new ClassPathXmlApplicationContext(configs);
    		ApplicationContext app5=new ClassPathXmlApplicationContext("classpath:config/applicationContext*.xml");
    	}

     

    3. 使用注解向IOC容器中添加bean:

  • 首先要在Spring配置文件中开启组件扫描
    <?xml version="1.0" encoding="UTF-8"?>
    <!--省略xml约束-->
    <beans>
    	<!-- Spring注解开发:通过注解来管理Spring的bean -->
    	<!-- 开启组件扫描,用以扫描指定包内带有实例化注解的类 -->
    	<context:component-scan base-package="package"></context:component-scan>
    
    </beans>

     

  • 对象实例化的注解有四种,分别是:通过注解进行实例化时,必须保证类中有默认构造方法
    • @Component:指定该类为一个普通bean,默认id为类名首字母小写,也可指定id,如@Component("user")
    • @Repository:指定该类为一个持久层bean,默认id为类名首字母小写,也可指定id,如@Repository("user")
    • @Service:指定该类为一个业务层bean,默认id为类名首字母小写,也可指定id,如@Service("user")
    • @Controller:指定该类为一个控制层bean,默认id为类名首字母小写,也可指定id,如@Controller("user")
  • @Scope("prototype"/"singleton"):该注解指定bean的作用域,该注解要与以上注解搭配使用,singleton表示容器中只生成一个实例,也就是单例模式,默认为该模式;而prototype表示会生成多个实例,每访问一次容器就创建一次

3. DI(依赖注入)

    1. 即IOC容器在运行期间动态的将对象的依赖关系注入到对象的属性中,底层原理为:首先生成类对象,依据所依赖的属性类型生成属性实例,然后通过set方法来实现注入,或通过有参构造器在生成类的实例时注入所依赖的属性实例
    2. 依赖注入的实现方式有两种:有参构造器实现注入、set方法实现注入

    3. 通过配置文件配置依赖注入:有参构造器在上面的IOC介绍中已经演示

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
	xmlns:jee="http://www.springframework.org/schema/jee" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
	
	<!--set方法实现注入-->
	<bean id="user" class="UserData"></bean>
	<bean id="book" class="Book">
	<!-- property标签:指定注入的属性 
		name属性用来指定类中需要注入的属性名,由set方法后的字符串首字母小写决定,即调用注入的set方法时将由set+name属性值
		来决定调用那个set方法
		ref属性表示被注入的bean的id
		value属性表示一个具体的值,用于java中的简单类型
	-->
		<property name="user" ref="user"></property>
	</bean>
	
	<!-- set方法可以注入的属性类型 -->
	<bean id="queryVo" class="QueryVo">
	<!-- 基本类型 -->
	<property name="t1" value="vn"></property>
	<property name="t2" value="1"></property>
	<!-- pojo类型 -->
	<property name="t3" ref="user"></property>
	<!-- List类型   List<String> -->
	<property name="t4">
		<list>
			<value>vn</value>
		</list>
	</property>
	<!-- List类型   List<UserData> -->
	<property name="t5">
		<list>
			<ref bean="user"/>
		</list>
	</property>
	<!-- Map类型 -->
	<property name="t6">
		<map>
			<entry key="1" value="vn"></entry>
		</map>
	</property>
	<!-- Properties类型 -->
	<property name="t7">
		<props>
			<prop key="name">vn</prop>
		</props>
	</property>
	</bean>
</beans>

    4. 通过注解进行依赖注入:

  • 首先需要开启Spring组件扫描,并且要保证注入的属性实例的类以及被注入的类都在Spring容器中
  • @Autowired:直接标记在属性上,依据属性类型进行注入,即依据该类型在容器中查找相同类型或基类的bean进行注入,若依据类型查找到多个bean,则会报错,可以在要注入的bean的类前添加实例注解时指定bean的id即可避免,也可以写在set方法上, @Autowired会依据set方法中的参数类型来查找bean
  • @Qualifier("id"):该注解要写在@Autowired之后,搭配使用,用来指定要注入的bean的id,也可以避免上面的错误, 这两个注解也可以写在set方法上
  • @Resource(name="user"):相当于@Autowired+@Qualifier(""),直接依据id查找,@Autowired是由Spring提供的,而@Resource是由jdk提供的
@Component("book")
@Scope("prototype")
public class Book implements Serializable {
	private String cn_notebook_id;

	//@Autowired
	//@Qualifier("user")
	@Resource(name="user")
	private UserData user;

	public UserData getUser() {
		return user;
	}

	//@Autowired
	//@Qualifier("user")
	public void setUser(UserData user) {
		this.user = user;
	}
	public String getCn_notebook_id() {
		return cn_notebook_id;
	}
	public void setCn_notebook_id(String cn_notebook_id) {
		this.cn_notebook_id = cn_notebook_id;
	}
}

 

© 著作权归作者所有

江左煤郎

江左煤郎

粉丝 26
博文 97
码字总数 238387
作品 0
西安
后端工程师
私信 提问
那些年,我们一起追的Spring

学无止境,但仍需及时总结。 自去年开始写作以来,写了一些关于Spring的文章,今天将它们汇总起来,一方面方便大家阅读,另一方面,也是一次小的复盘总结。 IOC 首先是Spring的IOC,也就是控...

SexyCode
2018/08/14
0
0
Java程序员从笨鸟到菜鸟之(六十七)细谈Spring(一)spring简介

Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。 然而...

长平狐
2012/11/12
122
1
spring和springmvc的区别

spring 是一个开源框架,是为了解决企业应用程序开发,功能如下 ◆目的:解决企业应用开发的复杂性 ◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能 ◆范围:任何Java应用 ...

明理萝
2018/07/30
60
2
【Spring】——IoC原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fjj15732621696/article/details/80869251 在spring的学习总总是有IOC(控制反转)和DI(依赖注入),感觉这两...

DD_Davina
2018/06/30
0
0
【Spring学习笔记】--IOC学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/YYZZHC999/article/details/82824751 spring ioc原理 Ioc—Inversion of Control,即“控制反转”,不是什么技...

Hepburn_Yang
2018/09/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
昨天
64
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
昨天
26
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
昨天
41
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
昨天
27
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
昨天
44
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部