Spring5_IOC(原理级学习)

尚硅谷课堂笔记:

链接: https://pan.baidu.com/s/1BPdI_vDWW2M-1A0okF3Pww 提取码: 2333
视频的代码笔记和资料。

老师笔记中的某些内容不再赘叙

此笔记 针对以上笔记为基础 添加补充

主要目的为针对自己复习学习

入门案例

public class TestSpring5 {

    @Test
    public void testAdd(){

        //1.加载spring配置文件
        /*
        在src下 ,写下面这个(类路径)
        new FileSystemXmlApplicationContext()不同
        写绝对路径 D:\Mozilla Firefox\aa......
         */
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2.获取配置创建的对象
        User user1 = context.getBean("user1", User.class);
        user1.add();
    }
}
public class User {
    public void add(){
        System.out.println("add....");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<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">
    <!-- 配置User对象创建-->
    <bean id="user1" class="com.company.Spring5.User"></bean>
</beans>

一.IOC

image-20220308183759166

调用过程 也就是在其他类里 去new 一个类,

虽然省去了new, 但是要到配置文件读取,配置文件中也得说明

目前还看不出来它的强大

1.IOC原理理解

image-20220308185159566

问题:

image-20220308193444373

dao路径变化了 方法变了 Service 都要变,耦合度高

这不满足 迪米特原则(最少知道原则)

目的:耦合度减低到最低

解决方法一(最终方法是IOC):工厂模式

image-20220308200809070

这样解耦 还没有到达最低

解决方法二:IOC(xml+反射)

image-20220308202634815

这样只需要改xml的class 就可以改动类,类似于定义变量,修改不用一个一个改

2.IOC接口

image-20220309210903236

使用第二种 因为服务器启动时 可以慢,而且第一种是内部使用的接口

image-20220309212426404

3.IOC —Bean管理操作

image-20220309213400767

image-20220309220544081

以下是xml Bean管理操作

image-20220309222246439

User user1 = context.getBean("user1", User.class);

上面的代码 如果没有无参构造会报错

image-20220309222645785

DI :Dependency Injection

DI 是IOC的一种具体实现。需要在创建对象的基础上完成

第一种注入方式:使用 set 方法进行注入

  • (1)创建类,定义属性和对应的 set 方法
  • (2)在 spring 配置文件配置对象创建,配置属性注入
    八种基本类型 + String类型注入使用+Date类型 使用value属性进行赋值
    对象类型 使用ref
    详细的文章
    在这里插入图片描述

第二种注入方式:使用有参数构造进行注入

  • (1)创建类,定义属性,创建属性对应有参数构造方法

  • (2)在 spring 配置文件中进行配置

<bean class="cdi.EmpDAOImpl" id="empDAO">
    <!--使用构造注入-->
    <constructor-arg index="0" name="name" value="小黑黑"/>
    <constructor-arg index="1" name="age" value="23"/>
    <constructor-arg index="2" name="bir" value="2012/12/12"/>
    <!--注入数组-->
    <constructor-arg index="3" name="qqs">
        <array>
            <value>小黑</value>
            <value>小名</value>
            <value>小陈</value>
        </array>
    </constructor-arg>
    <!--注入list-->
    <constructor-arg index="4" name="habbys">
        <list>
            <value>好人</value>
            <value>坏蛋</value>
            <value>小豆豆</value>
        </list>
    </constructor-arg>
</bean>

作者:嘿_鱼骨头
链接:https://juejin.cn/post/7088814727081492517
```xml

第三种注入方式:p名称空间

> 就是 标签的 p属性
>
> 其实底层还是第一种方法



### 4. 注入null和特殊值

![image-20220310113736533](https://img-blog.csdnimg.cn/img_convert/864bcec48b7876d62cf4e77d259cd4d3.png)

![image-20220310142707384](https://img-blog.csdnimg.cn/img_convert/34132f12a068e29ae8741f7c7816c1bd.png)

xml语法那部分讲过的,cdata纯文本区域,不需要xml解析,自然不会错误识别了

### 5.注入属性—外部bean

解答:创建实例很费时间,通过配置文件的方式可以在服务器运行过程中提高速度,同时好管理好维护,

```xml
<bean id="UserService" class="com.company.Spring5.service.UserService">
    <property name="userDao" ref="userDaoImpl"></property>
</bean>

<bean id="userDaoImpl" class="com.company.Spring5.dao.UserDaoImpl"></bean>
public class UserDaoImpl implements UserDao {

    @Override
    public void update() {
        System.out.println("dao.update");
    }
}
public class UserService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void add() {
        System.out.println("service.add");
    }
}

6.内部bean和级联赋值

外部bean可以通过ioc获取,内部的获取不到

<bean id="emp1" class="com.company.Spring5.bean.Emp">
    <property name="empName" value="ZS"></property>
    <property name="gender" value="man"></property>
    <property name="dept">
    <!--就是属性也是个对象,这个对象有自己的小属性-->
        <bean id="dept1" class="com.company.Spring5.bean.Dept">
            <property name="deptName" value="KF"></property>
        </bean>
    </property>
</bean>
public class Emp {
    private String empName;
    private String gender;
    //部门
    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

以上的效果和上面的外部bean 一样

image-20220310215954566

image-20220310220931712

方法二需要生成get方法

image-20220310220123574

7.注入集合类属性

<?xml version="1.0" encoding="UTF-8"?>
<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="stu" class="com.company.Spring5.bean.Stu">
        <!--数组类型注入-->
        <property name="courses" >
            <array>
                <value>java课程</value>
                <value>数据库课程</value>
            </array>
        </property>

        <!--list类型注入-->
        <property name="list">
            <list>
                <value>张三</value>
                <value>法外狂徒</value>
            </list>
        </property>
        <!--map类型注入-->
        <property name="map">
            <map>
                <entry key="skill1" value="java"></entry>
                <entry key="skill2" value="php"></entry>
            </map>
        </property>
        <!--set类型注入-->
        <property name="set">
            <set>
                <value>Mysql</value>
                <value>Redis</value>
            </set>
        </property>
    </bean>
</beans>
public class Stu {
    private String[] courses;
    private List<String> list;
    private Map<String, String> map;
    private Set<String> set;

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setCourses(String[] courses) {
        this.courses = courses;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }
}

注入值是对象的情况

<!--创建多个 course 对象--> 
<bean id="course1"class="com.atguigu.spring5.collectiontype.Course">
 	<property name="cname" value="Spring5 框架"></property>
</bean>
<bean id="course2" class="com.atguigu.spring5.collectiontype.Course">
 	<property name="cname" value="MyBatis 框架"></property>
</bean>
<!--注入 list 集合类型,值是对象-->
  <property name="courseList">
 	<list>
 		 <ref bean="course1"></ref>
		 <ref bean="course2"></ref>
 </list>
</property>

集合注入部分提取

image-20220311214439416

好像 一个公共类里面的公共方法

image-20220311215249831

8.FactoryBean

FactoryBean 和BeanFactory 没有区别

image-20220312122605435

工厂bean 就是xml 定义的类型 和 读取xml 后实际创建出来的bean类型不一样

9.Bean的作用域

1、在Spring里面,设置创建bean实例是单实例还是多实例。

默认情况下是单实例

@Test
public void test2(){

    ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
    //2.获取配置创建的对象
    Book t1 = context.getBean("t1", Book.class);
    System.out.println(t1);
    Book t11 = context.getBean("t1", Book.class);
    System.out.println(t11);
    //com.company.Spring5.Book@72e5a8e
    //com.company.Spring5.Book@72e5a8e
}
<?xml version="1.0" encoding="UTF-8"?>
<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="t1" class="com.company.Spring5.Book"></bean>
    
</beans>

设置是单实例还是多实例:

image-20220312135527392

<?xml version="1.0" encoding="UTF-8"?>
<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="t1" class="com.company.Spring5.Book" scope="prototype"></bean>

</beans>
public void test2(){

    ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
    //2.获取配置创建的对象
    Book t1 = context.getBean("t1", Book.class);
    System.out.println(t1);
    Book t11 = context.getBean("t1", Book.class);
    System.out.println(t11);
    //com.company.Spring5.Book@29215f06
    //com.company.Spring5.Book@59505b48
}

image-20220312154433465

10.Bean的生命周期

image-20220312155833994

1,2 步上面已经演示过了

第三步 是自己根据需要配置的,

image-20220312160903205

image-20220312160931519

image-20220312161604259

同样是自己配置的

image-20220312161746776

但是 销毁需要手动使用 .close() 才会去调用你配置的销毁方法。

image-20220312162053311

bean的后置处理器,bean生命周期有七步

在实现BeanPostProcessor接口后 还有两步,可以在 初始化前初始化后 调用

1)通过构造器创建 bean 实例(无参数构造)

2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)

3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization

4)调用 bean 的初始化的方法(需要进行配置初始化的方法)把bean实例传递bean后置处理器的方法postProcessAfterInitialization

6)bean 可以使用了(对象获取到了)

7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法

实际开发的时候可以在项目启动时就获取到Bean对象,比如希望做一个过滤器链,可以存放到Map中在调用的时候直接从Map中获取,就不用在使用getBean方法了

image-20220312173456032

配置之后所以的bean 都添加了后置处理器(好像是类似过滤器的那种)

image-20220312173515506

11.XML管理方式(自动装配)(实际开发直接用注解方式 自动装配)

上面使用 或者外部bean的方法属于手动装配

<!--
  以前的外部bean方式的属性注入
<bean id="emp" class="com.company.Spring5.Autowire.Emp2">
    <property name="Dept2" ref="dept" ></property>
</bean>
<bean id="dept" class="com.company.Spring5.Autowire.Dept2"></bean>
-->

byName根据属性名称: 就是根据set方法注入

 <!--实现自动装配
 bean标签属性autowire,配置自动装配
 autowire属性常用两个值:
 byName根据属性名称注入  注入值bean的id值和类属性名称一样 我类的属性名字是dept2 下面那个标签的id 也是dept2
 byType根据属性类型注入-->
<bean id="emp2" class="com.company.Spring5.Autowire.Emp2" autowire="byName">
</bean>
<bean id="dept2" class="com.company.Spring5.Autowire.Dept2"></bean>

image-20220312185145102

byType根据属性类型注入:

<bean id="emp2" class="com.company.Spring5.Autowire.Emp2" autowire="byType">
</bean>
<bean id="dept2" class="com.company.Spring5.Autowire.Dept2"></bean>

下面这种就会报错 ,有两个Dept2类型的bean

<bean id="emp2" class="com.company.Spring5.Autowire.Emp2" autowire="byType">
</bean>
<bean id="dept2" class="com.company.Spring5.Autowire.Dept2"></bean>
<bean id="dept3" class="com.company.Spring5.Autowire.Dept2"></bean>

12.引入外部属性文件

引入namespace(命名空间)其实就是为了解析那个标签,spring默认引入的只有4个默认的标签

这个是使用schema技术对这个xml文件进行约束

<?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 id=" dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>
    -->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

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

以下是注解 Bean管理操作

image-20220313120753017

13.创建对象

image-20220313121220504

4种功能没有区别 都可以创建对象 命名不同 开发更清晰而已(约定大于配置)

image-20220313162723596

<?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">
    <!-- 开启组件扫描-->
    <!--多个逗号分开-->
    <context:component-scan base-package="com.company.Spring5.dao,com.company.Spring5.service"></context:component-scan>

    <!--或者写上层路径-->
    <context:component-scan base-package="com.company.Spring5"></context:component-scan>


</beans>
//括号中的值可以不写默认首字母小写,就是userService
//等价于bean标签的Id ,上面的其他3种效果也一样
@Component(value = "userService")
public class UserService {
    public void add() {
        System.out.println("service.add");
    }
}
public class TestBean {
    @Test
    public void testService() {
    ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();

    }

}

14组件扫描细节

例1:

在设置的包中只扫描Controller注解

image-20220313165336192

user-default-filters=“fasle” 时候 不写 includ-filter 就不会扫描包

例2:

在设置的包中除了Controller 其他的都扫描

image-20220313165621172

15.属性注入

image-20220314205036572

autowired根据bytype quilife根据byname reources可以根据byname也可以根据bytype

image-20220314205112044

  • image-20220314210151309
@Component(value = "userService")//等价于bean标签的Id
public class UserService {
    @Autowired
    private UserDao userDao;
    public void add() {
        System.out.println("service.add");
    }
}
@Repository
public class UserImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("UserDao.add");
    }
}

如果多个实现类可能就要指定名称 上面的例子中只有一个实现类

  • image-20220314215515525
@Component(value = "userService")//等价于bean标签的Id
public class UserService {
    @Autowired
    @Qualifier(value = "userImpl1")
   	private UserDao userDao;

    public void add() {
        System.out.println("service.add");
        userDao.add();
    }
}
@Repository(value = "userImpl1")
public class UserImpl implements UserDao{

    @Override
    public void add() {
        System.out.println("UserDao.add");
    }
}
  • @Resource注解是javax.annotacion包下的,属于java的扩展包,在标准jdk中没有 。需要导入

image-20220314215705003

import javax.annotation.Resource;
  • image-20220314224119841

    @Value(value = "aaa")
    private String name;
    

16.纯注解开发

了解,实际中使用Springboot开发

(1)创建配置类 替代xml(中开启组件扫描)

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

@Configuration //当前类作为配置类
@ComponentScan(basePackages = {"com.company"})
public class SpringConfig {

}

(2)测试类

@Test
public void testSpringConfig() {
    ApplicationContext context =new AnnotationConfigApplicationContext(SpringConfig.class);
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值