Spring最好的一篇文章——IOC容器

IOC容器

  • 1. IOC的概念及原理
  • 2. Bean 管理操作实现的两种方式(xml配置文件实现)
    • 2.1 基于xml方式创建对象
    • 2.2 基于xml方式注入属性
    • 2.3 xml注入其他类型属性(空值或特殊符号)
    • 2.4 xml注入外部bean
    • 2.5 注入属性-内部bean
    • 2.6 级联注入
    • 2.7 注入array、list、map、set属性
    • 2.8 注入List对象泛型
    • 2.9 集合注入值抽取
    • 2.10 工厂bean
    • 2.11 bean的作用域
    • 2.12 bean的生命周期
    • 2.13 xml自动装配
    • 2.14 外部属性文件
  • 3. Bean 管理操作实现的两种方式(基于注解方式实现)
    • 3.1 bean基于注解创建对象
    • 3.2 组件扫描的配置
    • 3.3 基于注解实现属性注入
    • 3.4 全注解开发

1. IOC的概念及原理

⭐ 什么是IOC?

(1) 控制反转, 就是把对象创建和对象之间的调用过程,交给Spring进行管理。
(2) 使用IOC的目的: 为了降低耦合度——解耦。
(3) 上面的入门案例就是IOC的实现

⭐ IOC底层原理

(1) xml解析、 工厂模式、反射

⭐ IOC(接口)

  1. IOC思想基于IOC的容器完成,IOC容器底层就是对象工厂
  2. Spring提供IOC容器实现两种方式:(两个接口)
    (1) BeanFactory, IOC容器的基本实现,是Spring内部的使用接口,不提供给开发人员使用。
    (2) ApplicationContext:BeanFactory接口的子接口。提供更多强大的功能,一般由开发人员调用使用。
  3. ApplicationContext接口实现类有很多实现类。

2. Bean 管理操作实现的两种方式(xml配置文件实现)

⭐ 什么叫Bean管理?

Bean 管理指的是两个操作—— ☀ Spring创建对象、☀ Spring注入属性

2.1 基于xml方式创建对象

(1) 创建实体类
(2) spring的xml配置文件中配置bean标签

	
	<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.jzq.spring5.pojo.User">bean>
	beans>

(3) 创建对象时候,默认也是执行☀无参数构造方法完成对象的创建。

2.2 基于xml方式注入属性

DI: 依赖注入,就是注入属性.

(1)使用set方法进行注入.

⭐ 创建对应实体类,以及对应成员属性的set方法
⭐ 这类注入必须有无参构造器

	package com.jzq.spring5.pojo;

	public class Book {
	    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 void show() {
	        System.out.println(this.getName() + ":" + this.getAge());
	    }
	}
				

⭐ 在spring配置文件配置对象创建,配置属性注入。

	
	<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="book" class="com.jzq.spring5.pojo.Book">
	        
	        <property name="name" value="天龙八部">property>
	        <property name="age" value="15">property>
	    bean>
	beans>

(2) 使用有参构造进行注入

⭐ 创建对应的实体类,要有构造方法

	package com.jzq.spring5.pojo;
	
	public class User {
	    public int age;
	
	    public void show() {
	        System.out.println("hello,spring5");
	    }
	}

⭐ 在spring配置文件中进行配置

	
	<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.jzq.spring5.pojo.User">bean>
	
	    
	    <bean id="book" class="com.jzq.spring5.pojo.Book">
	        
	        <property name="name" value="天龙八部">property>
	        <property name="age" value="15">property>
	    bean>
	
	    
	    <bean id="orders" class="com.jzq.spring5.pojo.orders">
	        <constructor-arg name="uuid" value="4d5s45da4sdsa445sa">constructor-arg>
	    bean>
	beans>

(3) 使用p名称空间注入(了解——set实现)

⭐ 使用p名称空间注入,可以简化基于xml配置方式
第一步 添加p名称空间在配置文件中

	<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

⭐进行属性注入,在bean标签内进行操作

    <bean id="bookp" class="com.jzq.spring5.pojo.Book" p:name="11" p:age="151">bean>

2.3 xml注入其他类型属性(空值或特殊符号)

⭐1.字面量

(1)null值


<property name="addree">
	<null>null>
property>

(2)属性包含特殊符号


<property name="addree">
	<value>>]]>value>
property>

2.4 xml注入外部bean

1 . 先写好逻辑层和Mapper层结构
⭐IOC容器创建的UserService对象可以调用UserMapper中操作数据库的方法。

Spring最好的一篇文章——IOC容器_第1张图片

2 . 注意看一下UserService中如何实现UserMapper实现类.
⭐ 通过xml注入(set方式),将UserMapperImpl对象注入到UserService的对象中。因为UserService中的是UserMapper的接口,所以注入实现类对象时,其实是一种多态的形式!具体注入方式看第三条的xml关系。

Spring最好的一篇文章——IOC容器_第2张图片

3 . 配置外部bean注入的xml
⭐ xml注入属性UserService,属性为userMapper。 由于注入的并不是一个值,而是一个对象类型(UserMapper),所以用ref进行绑定,而不是value。其中ref绑定的是一个UserMapperImpl实现类的bean的id值。


    <bean id="userservice" class="com.jzq.spring5.service.UserService">
        
        <property name="userMapper" ref="userMapperIpml">property>
    bean>

    <bean id="userMapperIpml" class="com.jzq.spring5.mapper.UserMapperImpl">bean>

2.5 注入属性-内部bean

⭐ 一对多的关系
1.注意两个实体类之间的联系, 每个员工类中都有一个部门成员属性

	private int age;
    private String name;
    Department department;

xml的配置如下


    <bean id="worker" class="com.jzq.spring5.pojo.Workers">
        <property name="name" value="贾俊贤">property>
        <property name="age" value="15">property>
        <property name="department">
        	
            <bean id="department" class="com.jzq.spring5.pojo.Department">
                <property name="name" value="协和部">property>
            bean>
        property>
    bean>

2.6 级联注入

⭐ 第一种方案

xml如下


    <bean id="worker2" class="com.jzq.spring5.pojo.Workers">
        <property name="name" value="贾俊贤2">property>
        <property name="age" value="19">property>
        <property name="department" ref="department2">property>
    bean>
    
    <bean id="department2" class="com.jzq.spring5.pojo.Department">
        <property name="name" value="协和部2">property>
    bean>

⭐ 第二种方案

这张方案需要设置访问器(get)

 public Department getDepartment() {
        return department;
    }

xml如下


    
    <bean id="worker3" class="com.jzq.spring5.pojo.Workers">
        <property name="name" value="贾俊贤3">property>
        <property name="age" value="19">property>
        <property name="department" ref="department3">property>
        <property name="department.name" value="协和部3">property>
    bean>
    
    <bean id="department3" class="com.jzq.spring5.pojo.Department">
    bean>

2.7 注入array、list、map、set属性

⭐ 这里只是最简单的元素注入
xml 如下

<bean id="ceshi" class="com.jzq.spring5.popj.TestLei">
        
        <property name="array">
            <array>
                <value>xxxvalue>
                <value>xxxxvalue>
                <value>xxxxxvalue>
            array>
        property>

        
        <property name="list">
            <list>
                <value>大厦大火傻大个value>
                <value>dsadadssadasvalue>
            list>
        property>

        
        <property name="map">
            <map>
                <entry key="姓名" value="xx">entry>
                <entry key="年龄" value="58">entry>
            map>
        property>

        
        <property name="set">
            <set>
                <value>大撒大撒单dvalue>
                <value>dsadsdasvalue>
            set>
        property>
    bean>

2.8 注入List对象泛型

⭐ 第一种方式: 这种方式通过 ref链接到对象

	<bean id="ceshi" class="com.jzq.spring5.popj.TestLei">
        
        <property name="bookList">
            <list>
                <ref bean="b1">ref>
                <ref bean="b2">ref>
            list>
        property>
    bean>

    <bean id="b1" class="com.jzq.spring5.popj.Book">
        <property name="books">
            <list>
                <value>d7sad7sad7as7value>
                <value>d7sad7sad7as7value>
                <value>d7sad7sad7as7value>
            list>
        property>
    bean>

    <bean id="b2" class="com.jzq.spring5.popj.Book">
        <property name="books">
            <list>
                <value>233123value>
                <value>d7213231237value>
                <value>d7sad21323127sad7as7value>
            list>
        property>
    bean>

2.9 集合注入值抽取

⭐ 在spring中引入命名空间util:


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       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
                            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
 

⭐ 使用抽取出的数值进行注入


    <util:list id="book">
        <value>dasdsadsadvalue>
        <value>dsadsdsd7s8d7sd8value>
    util:list>
    
    <bean id="books" class="com.jzq.spring5.popj.Book">
        <property name="books" ref="book">property>
    bean>

2.10 工厂bean

通过配置工厂bean返回具体实例
⭐ 工厂类:要实现 FactoryBean 接口

package com.jzq.spring5.popj;

import org.springframework.beans.factory.FactoryBean;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;

public class Mybean implements FactoryBean<Book> {
    @Override
    public boolean isSingleton() {
        return false;
    }

    @Override
    public Book getObject() throws Exception {
        Book book = new Book();
        List<String> list = new ArrayList<>();
        list.add("dsaadad");
        list.add("dsaadad");
        list.add("dsaadad");
        book.setBooks(list);
        return book;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}

xml 配置如下:


    <bean id="myBean" class="com.jzq.spring5.popj.Mybean">bean>

2.11 bean的作用域

⭐ bean是单实例还是多实例?

在Spring中,设置创建的bean实例默认是单实例对象。

⭐ 如何设置bean是单实例还是双实例?

在bean标签内设置scope为singleton为单实例。
设置为prototype为多实例。

⭐ singleton单实例和prototype多实例区别

singleton: 默认, spring加载配置文件就创建实例对象。
prototype: 在调用getBean的时候创建实例对象。

<bean id="books" class="com.jzq.spring5.popj.Book" scope="prototype">
	<property name="books" ref="book">property>
bean>

2.12 bean的生命周期

⭐ bean的整个运行顺序

  1. 通过构造器创建bean实例(无参构造)
  2. 为bean的属性设置值,和对其他bean的引用(调用set方法)
  3. 如果加了bean的后置处理器: 把bean实例传递bean后置处理器的方法postProcessBeforeInitialization
  4. 调用bean的初始化方法(需要在bean标签配置初始化参数:init-method )
  5. 如果加了bean的后置处理器: 把bean实例传递bean后置处理器的方法postProcessAfterInitialization
  6. bean创建实例(获取到对象)
  7. 当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的参数:destroy-method)

⭐实体类如下:

package com.jzq.spring5.popj;

public class Orders {
    private int uid;

    // 运行无参构造
    public Orders() {
        System.out.println("第一步执行了无参构造");
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
        System.out.println("第二步执行了赋值set");
    }

    public void initMethod() {
        System.out.println("第三步执行初始化函数(需要在bean配置)");
    }

    public void destoryMethod() {
        System.out.println("第五步执行了销毁函数(需要在bean配置)");
    }

}

⭐ bean的后置处理器类:

package com.jzq.spring5.popj;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化bean前执行(配置了bean后置处理器)");

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化bean后执行(配置了bean后置处理器)");

        return bean;
    }
}

⭐ xml下的bean配置如下:

	<bean id="order" class="com.jzq.spring5.popj.Orders" init-method="initMethod" destroy-method="destoryMethod">
        <property name="uid" value="7878">property>
    bean>

    
    <bean id="myBeanPost" class="com.jzq.spring5.popj.MyBeanPost">bean>

2.13 xml自动装配

根据装配规则(属性名称或者属性类型) , spring自动将匹配的属性值进行注入

  1. 根据属性名自动注入

设置autowire参数为byType

	<bean id="c2" class="com.jzq.spring5.popj.C2" autowire="byName">bean>

    <bean id="c1" class="com.jzq.spring5.popj.C1">bean>
    <bean id="c3" class="com.jzq.spring5.popj.C1">bean>
  1. 根据属性类型自动注入

设置autowire参数为byType
⭐注意参数注入不要有多个相同类型的需要注入的bean

	<bean id="c2" class="com.jzq.spring5.popj.C2" autowire="byType">bean>

    <bean id="c1" class="com.jzq.spring5.popj.C1">bean>

2.14 外部属性文件

例如数据库连接
通过context命名空间引入

⭐db.properties文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://x.x.x.x:3306/mybatis?userSSL=true&useUnicode=true&charaterEncoding=UTF-8"
username="xxxxxxx"
password="xxxxxxxxxx"

⭐ xml引入如下


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                            http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd">

    
    <context:property-placeholder location="db.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driver}">property>
        <property name="url" value="${url}">property>
        <property name="username" value="username">property>
        <property name="password" value="password">property>
    bean>
beans>

3. Bean 管理操作实现的两种方式(基于注解方式实现)

⭐什么是注解?

注解是代码特殊标记,格式: @注解名称(属性名=属性值, …)。
使用注解的地方,注解作用在类上,方法上,属性上。
使用注解目的:简化xml配置

⭐spring针对bean管理中的创建对象提供的注解

  1. @Component
  2. @Service
  3. @Controller
  4. @Repository
    上面的四个注解功能一致,都是用来创建bean实例,只是在不同层去使用!

⭐使用注解应该配置的xml(扫描包)?

配置context
通过标签的base-package参数设置扫描的包,多个包的时候可以通过逗号隔开,或者写上层目录包


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
   
    <context:component-scan base-package="com.jzq.ddd">context:component-scan>

beans>

3.1 bean基于注解创建对象

实体类
@Component(value = “book”) == xml里的

package com.jzq.ddd.popj;


import org.springframework.stereotype.Component;

@Component(value = "book")
public class Book {
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void show() {
        System.out.println("wxq大傻瓜");
    }
}

3.2 组件扫描的配置

默认的 下 是use-default-filters=“true”,支持所有的注解扫描。设置为false时,我们可以自动去配置需要扫描的注解
是扫描某注解
是除了某注解外扫描,这里注意不要声明use-default-filters=“false”


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    
    

    
    <context:component-scan base-package="com.jzq.ddd" use-default-filters="false">
        
        
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    context:component-scan>

    <context:component-scan base-package="com.jzq.ddd">
        
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    context:component-scan>
beans>

3.3 基于注解实现属性注入

⭐ 介绍注解

@AutoWired: 根据属性类型进行自动装配 ⭐ 多个实现类的时候不可以使用。
@Qualifier: 根据属性名称进行注入, 注意要和实现类的注解@Repository(value = “xxx”) 一致。
@Resource: 也可以通过类型注入,也可以通过属性名注入,不是spring的注解,来源于javax.annotation.Resource。
@Value: 注入普通基本类型

⭐ 注意外部类要@Repository(value = “xxx”)注解

package com.jzq.ddd.mapper;

import org.springframework.stereotype.Repository;

@Repository(value = "userMapperImpl01")
public class UserMapperImpl implements UserMapper {

    @Override
    public void querySql() {
        System.out.println("查询到你要的数据了:" );
    }
}

⭐ 注入属性注解案例

package com.jzq.ddd.service;

import com.jzq.ddd.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service(value = "userService")
public class UserService {

    // 值类型

    @Value(value = "书世俗叔叔世俗叔叔")
    private String date;

    // 根据值类型去注入属性,如果有多个实现类的话这种方式将会报错
    @Autowired
    @Qualifier(value = "userMapperImpl01")
    private UserMapper userMapper;

    @Autowired
    // 根据属性名称进行注入
    // 注意点1: 和@Autowired同时使用
    // 注意点2: 实现类要用注解@Repository(value = "c2")
    @Qualifier(value = "c2")
    private UserMapper userMapper2;


    public void show(){
        System.out.println(userMapper);
        userMapper.querySql();
        userMapper2.querySql();
        System.out.println(date);
    }
}

3.4 全注解开发

配置类

package com.jzq.ddd.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com.jzq.ddd"})
// 这句话实际等于  
public class Config {
}

使用时注意: new AnnotationConfigApplicationContext(配置类.class)

 @Test
    public void test03() {
        /*
            全部注解开发
         */
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        UserService userService = context.getBean("userService", UserService.class);
        userService.show();
    }

你可能感兴趣的:(spring,1024程序员节,spring,java,ioc)