深入学习springIOC

目录

    • IOC本质
    • 一个案例
      • 导入Jar包
      • 编写代码
      • 思考
    • IOC创建对象方式
      • 通过无参构造方法来创建
      • 通过有参构造方法来创建
    • Spring配置
      • 别名
      • Bean的配置
      • import
    • 依赖注入(DI)
      • 构造器注入
      • set注入 (重点)
        • 常量注入
        • Bean注入
        • 数组注入
        • List注入
        • Map注入
        • Set(集合)注入
        • Null注入
        • Properties注入
      • 拓展注入实现
        • P命名空间注入 : 需要在头文件中假如约束文件
        • c 命名空间注入 : 需要在头文件中假如约束文件
    • Bean的作用域
    • Bean的自动装配
      • 环境搭建
      • byName
      • byType
      • 使用注解
        • @Autowired
        • @Qualifier
        • @Resource
        • @value
        • 衍生注解
        • @scope
      • 基于Java类进行配置
        • @import

来源参考,b站狂神说:https://www.bilibili.com/video/BV1WE411d7Dv?spm_id_from=333.999.0.0

IOC本质

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
深入学习springIOC_第1张图片
IOC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,
新版本的Spring也可以零配置实现IoC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用
时再从Ioc容器中取出需要的对象。
深入学习springIOC_第2张图片

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

一个案例

导入Jar包

<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-webmvcartifactId>
    <version>5.1.10.RELEASEversion>
dependency>

编写代码

  1. 编写一个Hello实体类
public class Hello {
    private String name;
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void show(){
        System.out.println("Hello,"+ name );
    }
}
  1. 编写我们的spring文件 , 这里我们命名为beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
       
    
    <bean id="hello" class="com.kuang.pojo.Hello">
    <property name="name" value="Spring"/>
    bean>
    
beans>
  1. 测试
@Test
public void test(){
    //解析beans.xml文件 , 生成管理相应的Bean对象
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    //getBean : 参数即为spring配置文件中bean的id .
    Hello hello = (Hello) context.getBean("hello");
    hello.show();
}

思考

  • Hello 对象是谁创建的 ? 【 hello 对象是由Spring创建的 】
  • Hello 对象的属性是怎么设置的 ? 【hello 对象的属性是由Spring容器设置的 】

这个过程就叫控制反转 :

  • 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的
  • 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .

依赖注入 : 就是利用set方法来进行注入的
IOC是一种编程思想,由主动的编程变成被动的接收
我们不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改, 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !
可以通过newClassPathXmlApplicationContext去浏览一下底层源码

IOC创建对象方式

通过无参构造方法来创建

  1. User.java
public class User {

    private String name;
    
    public User() {
    	System.out.println("user无参构造方法");
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void show(){
		System.out.println("name="+ name );
	}
}
  1. beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="user" class="com.kuang.pojo.User">
		<property name="name" value="kuangshen"/>
	bean>
	
beans>
  1. 测试类
@Test
public void test(){
	ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
	//在执行getBean的时候, user已经创建好了 , 通过无参构造
	User user = (User) context.getBean("user");
	//调用对象的方法 .
	user.show();
}

通过有参构造方法来创建

  1. User. java
public class UserT {

	private String name;
	
	public UserT(String name) {
		this.name = name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void show(){
		System.out.println("name="+ name );
	}
}
  1. beans.xml 有三种方式编写

<bean id="userT" class="com.kuang.pojo.User">
	
	<constructor-arg index="0" value="kuangshen2"/>
bean>


<bean id="userT" class="com.kuang.pojo.User">
	
	<constructor-arg name="name" value="kuangshen2"/>
bean>


<bean id="userT" class="com.kuang.pojo.User">
	<constructor-arg type="java.lang.String" value="kuangshen2"/>
bean>
  1. 测试
@Test
public void testT(){
	ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
	UserT user = (UserT) context.getBean("user");
	user.show();
}

Spring配置

别名

alias 设置别名 , 为bean设置别名 , 可以设置多个别名


<alias name="userT" alias="userNew"/>

Bean的配置




<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
	<property name="name" value="Spring"/>
bean>

import

<import resource="{path}/beans.xml"/>

依赖注入(DI)

  • 依赖注入(Dependency Injection,DI)。
  • 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
  • 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .

构造器注入

上面的案例

set注入 (重点)

要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写

  1. Address.java
public class Address {

	private String address;
	
	public String getAddress() {
		return address;
	}
	
	public void setAddress(String address) {
		this.address = address;
	}
}
  1. Student.java
public class Student {
	private String name;
	private Address address;
	private String[] books;
	private List<String> hobbys;
	private Map<String,String> card;
	private Set<String> games;
	private String wife;
	private Properties info;

// set和get方法自动生产,省略
// ...

常量注入

<bean id="student" class="com.kuang.pojo.Student">
	<property name="name" value="小明"/>
bean>

Bean注入

<bean id="addr" class="com.kuang.pojo.Address">
	<property name="address" value="重庆"/>
bean>
<bean id="student" class="com.kuang.pojo.Student">
	<property name="name" value="小明"/>
	<property name="address" ref="addr"/>
bean>

数组注入

<bean id="student" class="com.kuang.pojo.Student">
	<property name="name" value="小明"/>
	<property name="address" ref="addr"/>
	<property name="books">
		<array>
			<value>西游记value>
			<value>红楼梦value>
			<value>水浒传value>
		array>
	property>
bean>

List注入

<property name="hobbys">
	<list>
		<value>听歌value>
		<value>看电影value>
		<value>爬山value>
	list>
property>

Map注入

<property name="card">
	<map>
		<entry key="中国邮政" value="456456456465456"/>
		<entry key="建设" value="1456682255511"/>
	map>
property>

Set(集合)注入

<property name="games">
	<set>
		<value>LOLvalue>
		<value>BOBvalue>
		<value>COCvalue>
	set>
property>

Null注入

<property name="wife"><null/>property>

Properties注入

<property name="info">
	<props>
		<prop key="学号">20190604prop>
		<prop key="性别">prop>
		<prop key="姓名">小明prop>
	props>
property>

拓展注入实现

  1. User.java
public class User {
	private String name;
	private int age;
}

P命名空间注入 : 需要在头文件中假如约束文件

导入约束 : xmlns:p="http://www.springframework.org/schema/p"


<bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>

c 命名空间注入 : 需要在头文件中假如约束文件

导入约束 : xmlns:c="http://www.springframework.org/schema/c"


<bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>

Bean的作用域

在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,
bean就是由IoC容器初始化、装配及管理的对象
深入学习springIOC_第3张图片

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton"/>
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
<bean id="loginAction" class="com.foo.DefaultAccount" scope="request"/>
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

Bean的自动装配

  • 自动装配是使用spring满足bean依赖的一种方法
  • spring会在应用上下文中为某个bean寻找其依赖的bean。

Spring中bean有三种装配机制,分别是:

  1. 在xml中显式配置;
  2. 在java中显式配置;
  3. 隐式的bean发现机制和自动装配。

Spring的自动装配需要从两个角度来实现,或者说是两个操作:

  1. 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
  2. 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;

组件扫描和自动装配组合发挥巨大威力,使的显示的配置降低到最少。
推荐不使用自动装配xml配置 , 而使用注解 .

环境搭建

两个实体类,Cat Dog 都有一个叫的方法
深入学习springIOC_第4张图片
新建一个用户类 User
深入学习springIOC_第5张图片
编写Spring配置文件
深入学习springIOC_第6张图片

byName

autowire byName (按名称自动装配)

<bean id="user" class="com.kuang.pojo.User" autowire="byName">
	<property name="str" value="qinjiang"/>
bean>

byType

autowire byType (按类型自动装配)
使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一
的异常(一般都是默认单例的)

<bean id="user" class="com.kuang.pojo.User" autowire="byType">
	<property name="str" value="qinjiang"/>
bean>

使用注解

jdk1.5开始支持注解,spring2.5开始全面支持注解。

  1. 在spring配置文件中引入context文件头
xmlns:context="http://www.springframework.org/schema/context"

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
  1. 开启属性注解支持!
<context:annotation-config/>

@Autowired

  • @Autowired是按类型自动转配的,不支持id匹配。
  • 需要导入 spring-aop的包!
public class User {
	@Autowired
	private Cat cat;
	@Autowired
	private Dog dog;
}

Autowired(required=false) 说明: false,对象可以为null;true,对象必须存对象,不能为null。

//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;

@Qualifier

  • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
  • @Qualifier不能单独使用。
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;

@Resource

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
  • 其次再进行默认的byName方式进行装配;
  • 如果以上都不成功,则按byType的方式自动装配。
  • 都不成功,则报异常。
public class User {
	//如果允许对象为null,设置required = false,默认为true
	@Resource(name = "cat2")
	private Cat cat;
	@Resource
	private Dog dog;
	private String str;
}

@value

使用注解注入属性

  1. 可以不用提供set方法,直接在直接名上添加@value(“值”)
@Component("user")
// 相当于配置文件中 
public class User {
	@Value("秦疆")
	// 相当于配置文件中 
	public String name;
}
  1. 如果提供了set方法,在set方法上添加@value(“值”);
@Component("user")
public class User {
	public String name;
	@Value("秦疆")
	public void setName(String name) {
		this.name = name;
	}
}

衍生注解

  • @Controller:web层
  • @Service:service层
  • @Repository:dao层

功能与@Component,看项目组习惯

@scope

singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。

@Controller("user")
@Scope("prototype")
public class User {
	@Value("秦疆")
	public String name;
}

基于Java类进行配置

JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。

测试

  1. 编写一个实体类,Dog
@Component //将这个类标注为Spring的一个组件,放到容器中!
public class Dog {
	public String name = "dog";
}
  1. 新建一个config配置包,编写一个MyConfig配置类
@Configuration //代表这是一个配置类
public class MyConfig {

	@Bean //通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
	public Dog dog(){
		return new Dog();
	}
}

@import

  1. 我们再编写一个配置类!
@Configuration //代表这是一个配置类
public class MyConfig2 {
}
  1. 在之前的配置类中我们来选择导入这个配置类
@Configuration
@Import(MyConfig2.class) //导入合并其他配置类,类似于配置文件中的 inculde 标签
public class MyConfig {

	@Bean
	public Dog dog(){
		return new Dog();
	}
}

你可能感兴趣的:(spring全家桶,spring,java)