Spring IOC 自学笔记

1、概述

Spring框架是一个开源的J2EE应用程序框架;

2、IOC和AOP

IOC:控制反转,把创建对象过程交给Spring进行管理;
Aop:面向切面,不修改源代码进行功能增强;

3、什么是IOC

  • 概念:IoC是Inversion of Control的缩写,翻译成“控制反转”

  • IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦。

  • 软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。

  • 通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

  • 底层技术:
    xml解析
    设计模式—工厂模式
    反射

  • 个人理解IOC
    其实IOC与面向对象一样,将创建对象的权力交给IOC管理

4、IOC如何降低耦合

5、IOC(接口)

IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
Spring提供IOC容器实现两种方式

  • BeanFactory:IOC容器的基本实现,是spring内部的使用接口,不提供开发人员进行使用
  • ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能
    区别:
  • BeanFactory:加载配置文件时,不会创建对象,只有在使用时才会创建
  • ApplicationContext:加载配置文件时就创建了对象

ApplicationContext实现类:(区别有哪些?)
FileSystemXmlApplicationContext :加载配置文件时,写的时系统路径(盘符)
ClassPathXmlApplicationContext:加载配置文件时,写的是类路径
ApplicationContext context = new ClassPathXmlApplicationContext(bean.xml)

6、IOC操作Bean管理

  • bean管理有两个操作
    spring创建对象
    spring输入属性
  • bean管理有两个方式
    配置文件xml方式
    注解方式

7、IOC基于xml操作

  1. 创建对象
  • 配置xml,创建对象时默认使用无参的构造方法
<bean id="user" class="com.atguigu.spring5.User"></bean>
// id属性:创建唯一表示,用于创建对象找到对应的类
// class属性:则是指定对应的类路径
  1. DI注入,注入属性
  • set方法进行注入
<bean id="book" class="com.atguigu.Book">
    // property标签中,name属性的值是set方法名的值setname
    <property name="name" value="红楼梦"></property>
    <property name="price" value="99"></property>
</bean>

package com.atguigu;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import static org.junit.Assert.*;

public class BookTest {
    @Test
    public void bookTest() {
        ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
        Book book = context.getBean("book",Book.class);
        book.bookToString();
    }
}
  • 有参构造方法注入
<bean id="user" class="com.atguigu.User">
    <constructor-arg name="name" value="xiaoming"></constructor-arg>
    <constructor-arg name="age" value="12"></constructor-arg>
</bean>

package com.atguigu;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import static org.junit.Assert.*;

public class UserTest {

    @Test
    public void userTest() {
        ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
        // 根据配置文件bean标签的constructor-arg 标签属性
        User user = context.getBean("user",User.class);

        user.userTest();
    }
}

注入空值及特殊字符

  • 注入空值
<bean id="book" class="com.atguigu.Book">
    // property标签中,name属性的值是set方法名的值setname
    <property name="name" value="红楼梦"></property>
    <property name="price">
        <null/>
    </property>
</bean>
  • 注入特殊字符
// 转义的方法 

// CDATA方法
<bean id="book" class="com.atguigu.Book">
    // property标签中,name属性的值是set方法名的值setname
    <property name="name" value="红楼梦"></property>
    <property name="price">
        <value><![CDATA[<<南京>>]]></value>
    </property>
</bean>

8、注入外部bean

<bean id="userservice" class="com.atguigu.service.UserService">
    <property name="userDao" ref="userdaoimpl"></property>
</bean>

<bean id="userdaoimpl" class="com.atguigu.dao.Impl.UserDaoImpl">

</bean>

9、注入内部bean和级联

<!-- 级联bean注入 -->
<bean id="studentFour" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1001"></property>
    <property name="sname" value="小刚"></property>
    <property name="age" value="10"></property>
    <property name="gender" value="男"></property>
    <property name="clazz" ref="clazzOne"></property>
    <property name="clazz.cId" value="2"></property>
    <property name="clazz.cName" value="12班"></property>
</bean>

<bean id="clazzOne" class="com.atguigu.spring.pojo.Clazz">
    <!-- <property name="cId" value="1"></property> -->
    <!-- <property name="cName" value="11班"></property> -->
</bean>

<!-- 内部bean注入 -->
<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1001"></property>
    <property name="sname" value="小刚"></property>
    <property name="age" value="10"></property>
    <property name="gender" value="男"></property>
    <property name="clazz">
        <bean id="clazzInner" class="com.atguigu.spring.pojo.Clazz">
            <property name="cId" value="3"></property>
            <property name="cName" value="13班"></property>
        </bean>
    </property>
</bean>

10、注入集合类型的属性

<bean id="clazzFirst" class="com.atguigu.spring.pojo.Clazz">
    <property name="cId" value="4"></property>
    <property name="cName" value="集合班"></property>
    <property name="students" ref="studentList"></property>
</bean>

<util:list id="studentList">
    <ref bean="studentFour"></ref>
    <ref bean="studentFive"></ref>
</util:list>

11、IOC操作bean管理有两种

1、普通的bean,特点:
在配置文件中class属性中定义的什么类型就返回什么类型
2、工厂bean,FactoryBean,特点:
class定义的类型和返回的类型可以不一致

  • 定义一个类实现FactoryBean接口
  • 实现接口内的方法,在方法中定义返回的bean类型

12、bean的作用域

1)、在spring中、设置创建bean实例默认是单实例
2)、spring中,bean标签可以通过scop属性来设置单实例还是多实例;
3)、singleton和prototype

13、bean的生命周期

  • 通过构造器构造bean实例(无参构造器)
  • 为bean实例的属性设置值和对其他bean的引用
  • 调用后置处理器(需要实现BeanPostProcesser接口,并实现postProcessBeforeInitialization方法)
  • 调用bean初始化的方法(需手动配置初始化方法)
  • 调用后置处理器(需要实现BeanPostProcesser接口,并实现postProcessAfterInitialization方法)
  • bean可以使用了
  • 当容器关闭时,调用bean销毁的方法

14、IOC操作Bean管理(xml自动装配)

如果使用autowire="byType",则不能有俩个相同类型的bean

15、基于注解方式实现bean管理

16、基于注解创建对象

步骤:
1、引入依赖;
2、开启组件扫描

<?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"
       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">


    <!--基于注解实现bean管理,第二步:开启组件-->
    <!--  扫描指定的包,两种方式:
      1、指定每个包路径,用逗号隔开;
      2、指定多个包的上级目录;
      -->
    <context:component-scan base-package="com.atguigu.service,com.atguigu.dao"></context:component-scan>
    <context:component-scan base-package="com.atguigu"></context:component-scan>

3、使用注解创建对象

package com.atguigu.service;

import org.springframework.stereotype.Component;

// 使用注解创建对象
// value属性可以不写,默认值是类的名称首字母小写
@Component(value = "bookService") // value="bookService" 等同于<bean id = "bookService" class="..">
public class BookService {
    public void add(){
        System.out.println("bookservice的add方法!");
    }

}

17、开启组件扫描的细节

18、基于注解实现属性注入

@AutoWired:可以根据属性的类型进行注入

package com.atguigu.dao.Impl;

import com.atguigu.dao.CarDao;
import org.springframework.stereotype.Repository;

@Repository
public class CarDaoImpl implements CarDao {

    public void update(){
        System.out.println("car实现类!");
    }
}

// service类
package com.atguigu.service;

import com.atguigu.dao.CarDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CarService {

    // 不需要有set方法
    // 根据类型进行注入
    @Autowired
    private CarDao car;

    public void test(){
        System.out.println("service的方法");
        car.update();
    }
}

@Qualifier:可以根据属性的名称进行注入

// @Qualifer需要和@Autowired一起使用;
// 当一个接口有多个实现类时,@Autowired就不知道注入哪个类型,此时需要配合@Qualifer
//根据名称注入
package com.atguigu.dao.Impl;

import com.atguigu.dao.CarDao;
import org.springframework.stereotype.Repository;

@Repository(value = "carDaoImpl2")
public class CarDaoImpl implements CarDao {

    public void update(){
        System.out.println("car实现类!");
    }
}
// service类
package com.atguigu.service;

import com.atguigu.dao.CarDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class CarService {

    // 不需要有set方法
    // 根据类型进行注入
    @Autowired
    // value值和实现类的value值保持一致
    @Qualifier(value = "carDaoImpl2")
    private CarDao car;

    public void test(){
        System.out.println("service的方法");
        car.update();
    }
}

@Resource:可以根据属性的类型或者属性的名称进行注入
@Value:普通类型属性的注入

19、完全注解开发

1、创建配置类,替换xml配置文件

package com.atguigu.config;

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

// 添加注解,使得此类被spring识别为“配置类”;
@Configuration
// 使用注解开启注解扫描
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}

2、修改测试方法

@Test
public void test2() {
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    CarService carService = context.getBean("carService",CarService.class);

    carService.test();
}

20、DI和IOC

1、IOC是思想,DI是实现方式。

posted @   梁伯熹  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示