Spring框架之ioc

前言

    趁着产品经理同鞋在忙需求的时候,系统的把spring框架相关的知识整理了一下,工作之后自己也没在怎么去搭建过,都是拿现成的去用,后面的计划是ssm,springboot,以及一些在工作上可能会用到的开源技术。就酱

Spring是什么?

    Spring框架为基于java的应用提供了一个全面的编程和配置模型,为简化企业级应用而生,Spring的主要优势就是之一就是分层架构是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用,类似于一个管家,帮你管理大大小小的事务,解决现有问题。下面一组图是Spring的一些框架结构

Spring简介

  Spring包含的功能如下:

   IOC:控制反转,Spring的核心功能

   AOP:面向切面编程

   WEB:MVC结构的实现,与其他Web技术整合

   DAO:与JDBC整合和事务管理

   ORM:与ORM框架整合

   JEE:与JavaEE服务整合

SpringIOC

    Ioc,核心容器,提供Spring框架的基本功能(Spring Core),控制反转,指的是对象的控制权反转(交给)Spring,也可以这样解释:获取对象的方式变了,对象创建的控制权不是使用者,而是“框架”和“容器”,ioc就是指对象的创建,并不是在代码中用new操作的,而是通过Spring进行配置创建的,利用容器创建对象,然后注入的方式去使用。类似于,比如我要租房子,IOC就相当于担任了一个房屋中介的角色,我这时候只需要向中介提出我的需求,两室一厅啊,必须有电梯啊,距离地铁站近之类的,这个时候中介会根据我的需求给我安排一房子,我就可以去租这个房子了,如果这个房子我不满意,不符合我的要求,此时就可以向中介抛出异常,整个过程不在由我来控制,而是有中介这个类似容器的角色来控制。这就是Spring所提倡的开发方式,所有的类都在Spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

使用结构:

 

使用步骤:

    基于XML文件的Bean配置,首先是applicationContext.xml文件,这可是核心文件配置一个Bean,需要一个id去唯一标识他,用Class指定Bean对象的路径

<?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-4.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.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-4.1.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
	
	<!-- 
		向容器中添加一个对象 !
		class属性:指定要添加的对象的 类全称(包名+类名),必须传递的属性
		id属性:(不允许使用特殊字符)配置到容器中的对象的key , 我们在代码中获取到容器后 , 可以通过key获取这个创建的对象
			-	id的命名规范: 以类名命名, 首字母小写
		name属性:配置到容器中的对象的key, 我们在代码中获取到容器后 , 可以通过key获取这个创建的对象(早期)
	<bean id="person" class="cn.chf.bean.Person"></bean>
	
	

	
</beans>

  

然后下面是实体类和测试

package cn.chf.bean;

public class Person {

	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public Person() {
		super();
		
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "我叫"+name+",我今年"+age+"岁";
	}
	
}

  

 @Test
	public void Test(){
		// 通过一个配置文件, 创建一个容器对象
		/**
		 * 容器对象在创建时, 会读取配置文件
		 * 根据XML中的bean节点, 来创建一个个的对象, 并存储到容器中(存储的key , 为bean节点的id属性)
		 */
		ClassPathXmlApplicationContext beans = new ClassPathXmlApplicationContext("applicationContext.xml");
		Object o1 = beans.getBean("person");
	System.out.println(o1);		
	}

  

下面是测试结果,这说明已经成功

两种获取对象的方式:

1 使用getBean方法传入一个参数(上方的代码就是这种方式)(重点

  参数:传入bean节点的Id,获取这个对象

  案例  Object value= beans.getBean(key);

2 使用getBean方法传入两个参数

  参数1:bean节点的id属性,用来在容器中查找这个对象

  参数2:传入一个(class<T>)类型的参数,用来做此方法的返回值

传入两个参数案例

 public void Test11(){
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person p = context.getBean("person",Person.class);
		p.setAge(19);
		p.setName("Alves");
		System.out.println(p);

 

Spring容器创建创建Bean对象的三种方式

使用构造器来实例化(重点,上方第一种方式)

    <bean id=”标识符”class=”包名.类名”/>

   使用静态工厂方法实例化(了解)

<bean id=”标识符”class=”包名.类名” factory-method=”静态方法名”/>

   使用实例工厂方法实例化(了解)

<bean id=”标识符”factory-bean=”对象id” factory-method=”静态方法名”/>

容器中对象的初始化与销毁

     我们可以通过配置文件来管理容器中对象的生命周期,可以在容器中对象创建与销毁时,执行特定的代码块

方法1 在beans节点添加属性

      指定当前容器中所有的对象的初始化方法与销毁方法

      default-init-method=”init”

      容器默认在创建时,会检索此对象是否存在此方法,存在则调用,不存在不操作

       default-destory-method=”destory”

      容器默认在移除对象时,会检索此对象是否存在此方法,存在则调用,不存在不操作

方法2 在bean节点中添加属性

     init-method=”init”

    容器默认在创建时,会调用init方法,不存在则报错

    destory-method=”destory”

     容器默认在移除对象时,会调用destory,不存在则报错

 

Bean对象的作用域(scope)

 指定Spring容器创建bean对象的作用域

  Singleton :在每个SpringIoc容器中一个bean定义对应一个对象实例,默认项

  Prototype :一个bean定义对应多个对象实例

  Request   :在一次HTTP请求中,一个bean定义对应一个实例,仅限于web环境中

  Session   :在一个HTTPSession中,一个bean定义对应一个实例,仅限于web环境

  Global Session:在一个全局的HTTP session中,一个bean定义对应一个实例,仅在基于protlet的web应用中才有意义,protlet规范定义了全局Session概念;

默认情况下对象延迟实例化:

 类似单例设计模式的懒汉式

方法1

DI依赖注入

   容器可以建立Bean对象的关系,实现的技术途径就是DI依赖注入,SpringDI分为Setter注入和构造器注入两种容器在创建完成对象后,通过调用set方法完成信息的注入,使用set方法注入的话必须存在无参构造器,如果不存在则报错

   在bean节点中,加入子节点<property name=”属性名称” value=”值”></property>

   容器在创建完成对象后,通过调用构造器参数完成信息的注入name属性表示的并不是类中的成员属性的名称, 而是构造方法中形式参数列表的名称

  <constructor-arg name="属性的名称" value="值" ></constructor-arg>

 在构造方法中, 也可以通过索引进行传值 , 索引表示的是: 形式参数列表中的参数下标

<constructor-arg index="0" value="值" ></constructor-arg>

   Bean参数注入的信息类还可以分为字符串,集合,bean对象

  对象的自动装配

我们可以在bean节点中, 加入autowire属性来实现属性的自动装配操作,属性的取值范围:

no:默认设置 ,关闭自动装配

byName: 通过属性的名称 与 容器中的id进行匹配, 完成自动装配 ,如果一个对象中存在一个属性名称为book , 刚好在创建这个对象时, 容器中存在一个book对象, 那么自动装配!  byName不会判断传入的数据类型是否匹配,只要属性名称与id匹配 则装配,容器引起误!

byType: 通过类型完成自动装配 !举例: Person类中存在一个属性 private Book biubiubiu, 容器中已经配置了一个Book, id为book,当我们向容器中配置Person时, 发现属性比ubiubiu的类型与容器中id为book的对象的类型相同 ,自动完成装配!  (通过set方式完成,重点)

constructor: 与byType方式一致, 只是使用的时构造方法进行装配 !(了解)

autodetect: 自动根据类中是否存在无参构造器 来进行选择使用 byType/constructor , 如果存在无参构造器 , 则使用byType 

组件扫描(重点)

Spring提供了一套基于注解配置的使用方法。 使用该方法可以大大简化XML配置信息。

开启组件扫描,可以利用注解方式应用IOC(以后的代码编写一直用这个方式,但是有个弊端,只能操作自己编写的类,无法操作jar文件的类)

在applicationContext.xml中添加启用标记即可

<context:component-scan base-package="cn.**.**"/>

向容器中添加对象的方式

 1.  @Component  通用注解(控制器注入服务把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/)

      定义spring管理bean

 2.  @Repository  持久化层组件的注解 (DAO,实现dao访问)

    @Component扩展,被@Repository注解的POJO类表示DAO层实现,从而见到该注解就想到DAO层实现,使用方式和@Component相同;

 3.  @Service   业务层组件注解(Service,服务注入dao)

      @Component扩展,被@Service注解的POJO类表示Service层实现,从而见到该注解就想到Service层实现,使用方式和@Component相同;

 4.  @Controller  控制层组件注解(Controller注入服务)

    @Component扩展,被@Controller注解的类表示Web层实现,从而见到该注解就想到Web层实现,使用方式和@Component相同;

给容器中的对象更改多例与单例

在类上添加注解

@Scope(value="")

取值范围:

1.  singleton(默认单例):

    默认情况下, 容器在创建时 会加载配置文件中的bean节点 , 每一个创建的对象都会存储到容器中 ,在用户调用getBean获取时 , 返回这个对象 !

2.  prototype(多例):

    当设置了一个bean节点为多例时 , 容器在创建时, 不会加载这个bean节点, 当用户调用getbean获取时, 创建一个新的对象返回给调用者

3.  request(请求)

    仅限于web环境 , 在一次HTTP的请求中 ,对象时单例的!

4.  session(会话)

    仅限于web环境, 在一次会话中, 对象是单例的!

5.  global Session(全局会话)

 

  在全局的global session, 对象是单例的 !

给容器中的对象添加初始化方法与销毁方法

    初始化方法:

    在方法上添加注解 @PostConstruct

    销毁方法:

在方法上添加注解 @PreDestroy

注解基本数据类型的数据

在一个属性上添加@Value 来完成操作

通过表达式获取一个容器中的对象的属性值!

通过表达式完成:

    @Value("#{person.name}")

    private String name;

通过直接赋值完成:

    @Value("hello")

private String name;

指定对象之间的依赖关系

 1.  @AutoWired 通过构造方法/set方法完成装配  (自动)

 2.  @Qualifier 通过构造方法/set方法完成装配  (非自动)

 3.  通过@Resource 建立依赖关系的流程

   先默认使用byName方式 , 去容器查找是否存在对应的对象 ,如果存在则赋值,如果上面没有查询到, 再 根据byType, 进行容器的查询,如果存在则赋值如果上面两种方式 均未查到 ,则不赋值

这些就是SpringIOc的不部分内容了,如果有什么问题和建议请留言,我会及时处理的。

定义Spring管理Bean
posted @ 2018-09-30 09:58  阿维大大  阅读(262)  评论(0编辑  收藏  举报