Spring架构开荒

IOC 控制反转

Inversion of Control
控制反转 依赖注入
1 控制什么?

控制对象的创建以及销毁

2 反转什么?

将对象的控制权交给IOC容器

举例说明:

张三要回家
对象:

  • 小明 人
  • 车 奔驰 宝马
    在这里插入图片描述
    Audi.java
public class Audi{
	
	public void start(){
		System.out.println("Audi.start");
	}

	public void turnLeft(){
		System.out.println("Audi.start");
	}
	public void trunRight(){
		System.out.println("Audi.start");
	}
	public void stop(){
		System.out.println("Audi.start");
	}
}

传统方式

张三控制车辆的流程:
1 创建一辆车

Audi audi = new Audi();

2 控制车辆的启动 直行 左右转

audi.start();
audi.turnLeft();
audi.trunRight();
turn.stop();

3 销毁车辆

java的jcc组织垃圾回收处理掉

张三的其他需求

比如看电影

public void goMovice(){
		public void start(){
		System.out.println("Audi.start");
	}
	public void stop(){
		System.out.println("Audi.start");
	}
}

现在张三要换一辆Buick车

在Zhangsan.java当就需要全部更改
产生了高耦合性

改进方案 1

把车升级到张三的属性域里面
这样就降低了耦合度

public class ZhangSan {

    Buick car = new Buick();

    public void goHome(){
        car.start();
        car.turnRight();
        car.turnLeft();
        car.stop();
    }
}

改进方案 2

接口Car

public interface Car {

    public void start();
    public void turnLeft();
    public void turnRight();
    public void stop();
}

奔驰车实现这个车的接口

public class Audi implements Car{

    public void start(){
        System.out.println("Audi.start");
    }

在ZhangSan当中用构造方法传进去Car

   private Car car;
    public ZhangSan(Car car){
        this.car = car;
    }
   

到现在Car已经不用ZhangSan来创建了 由IOC来创建了

车辆的控制权完全交给了IOC

实现自己编写一个IOC的容器

在这里插入图片描述

约定
  • 所有的Bean的生命周期交由IOC容器管理
  • 所有被依赖的Bean通过构造方法执行注入
  • 被依赖的Bean需要优先创建(创建张三前先创建奥迪)

所有被依赖的Bean通过构造方法执行注入

    public HumanWithCar(Car car) {
        this.car = car;
    }

    private Car car;

Class003Test.java//测试IOC容器

public class Class003Test {

    private IoCConteainer ioCConteainer = new IoCConteainer();

    @Before//创建bean
    public void before(){
        ioCConteainer.setBean(Audi.class, "Audi");
        ioCConteainer.setBean(Buick.class, "Buick");
        ioCConteainer.setBean(ZhangSan.class, "ZhangSan","Audi");
        ioCConteainer.setBean(Lisi.class, "Lisi","Buick");
    }

    @Test//使用bean
    public void test(){
        Human ZhangSan = (Human) ioCConteainer.getBean("ZhangSan");
        ZhangSan.goHome();
        Human Lisi = (Human) ioCConteainer.getBean("Lisi");
        Lisi.goHome();
    }
}

Spring IOC入门

1 创建一个javabean

public class Bean{
	public Bean(){
		System.out.println("Bean.bean");
	}
}

2 在pom中加入spring的依赖

spring-core
spring-context

3 在resources文件夹下建立一个spring.xml文件

//class = 1 中创建的Bean 并给一个唯一标示id
<bena class = "bean" class="com.imooc.spring.ioc.class004.Bean">

//测试


public class Class004Test {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml);
        Bean bean = context.getBean("bean",Bean.class);
        System.out.println("bean = " + bean);
    }
}

在这里插入图片描述

实例化Bean方式

  • 构造方法实例化
  • 静态方法
  • 实例方法

构造方法实例化

1 创建Bean.java

public class Bean {
    public Bean(){
        System.out.println("Bean.bean");
    }
}

2 在spring.xml中配置bean

<bean class = "com.spring.ioc.class05.Bean1" id = "bean1"/>

3 在class005Test.java中实例


public class class005Test {
    @Test
    public void test(){
        //取上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        //通过context get一个Bean
        Bean bean = context.getBean("bean", Bean.class);
        System.out.println("bean = " + bean);
    }
}

静态方法实例化

1 创建一个BeanFactory.java
通过BeanFactory的getBean方法实例化Bean


public class Bean2Factory {
    public static Bean2 getBean2(){
        return new Bean2();
    }
}

2 spring.xml中进行配置

<bean class = "com.spring.ioc.Class05.Bean2Factroy" 
	factory-method = "getBean2" id = "bean2"/>

3 Class005Test.java

Bean2 bean2 = context.getBean("bena2", Bean2.class);

实例方法实例化Bean

1 创建一个Bean3Factory.java
通过BeanFactory的getBean方法实例化Bean


public class Bean3Factory {
    public static Bean3 getBean3(){
        return new Bean3();
    }
}

2 spring.xml中进行配置

    <bean class = "com.spring.ioc.Class05.Bean3" factory-bean = "bean3Factory"
                factory-method = "getBean3" id = "bean3"/>

3 Class005Test.java

        Bean3 bean3 = context.getBean("bean3",Bean3.class);
        System.out.println("bean3 = " + bean3);

给Bean取一个别名

1 name属性

<bean class = "myspring.Bean" name  ="bean1_1,bean1_2 " id = "bean1"/>

2 alias属性

    <alias name = "bean1" alias="bean1_3,bean1_4"/>

测试

Bean1 bean1_1 = context.getBean("bean1_1",Bean1.class);
System.out.println("bean1_1 = " + bean1_1);
Bean1 bean1_2 = context.getBean("bean1_2",Bean1.class);
System.out.println("bean1_2 = " + bean1_2);

但是这些名字不同的都是同一个Bean
在这里插入图片描述

在这里插入图片描述

注入Bean的方式

  • 构造方法注入Bean
  • set方法注入Bean
  • 集合类Bean的型注入
    • List
    • Set
    • Map
    • Propertise
  • null值注入
  • 注入时创建内部Bean

前期准备
AnotherBean.java

public class AnotherBean {
    
}

Bena.java


public class Bean {

    private AnotherBean anotherBean;
    private String string;



    public AnotherBean getAnotherBean() {
        return anotherBean;
    }

    public void setAnotherBean(AnotherBean anotherBean) {
        this.anotherBean = anotherBean;
    }

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }
}

构造方法注入Bean

在Bean.java中写入构造方法

    public Bean(AnotherBean anotherBean, String string) {
        this.anotherBean = anotherBean;
        this.string = string;
    }

spring.xml

//index:参数是构造方法中的第几个参数
//name:当前参数的参数名字
//type:参数的类型
//value: 给参数赋值 适合简单的数据类型 string integer  double float
//ref:复杂数据类型赋值	对应anotherbean的id
    <bean class = "com.example.controller.Bean" id = "bean">
        <constructor-arg index="0" name = "anotherBean"
                         type="com.example.controller.AnotherBean"
                         ref="anotherBean"/>
        <constructor-arg index="1" name="string"
                         type="java.lang.String"
                         value="aaaaa"/>
    </bean>

在这里插入图片描述
简单写法

    <bean class="com.example.controller.AnotherBean" id = "bean"
        c:anotherBean-ref="bean1" c:string="ccccc"
          p:anotherBean1-ref="bean1_1" P:string1="ddddd"
    />

    <util:property name="anotherBean1" ref = "anotherBean"/>
    <util:property name = "String1" value="ddddd"/>

在这里插入图片描述

set方法注入Bean

在这里插入图片描述

集合类型的Bean的注入
  • list
  • set
  • map
  • propertise

List
spring.xml

    <util:property name = "stringList">
        <list>
            <value>aaaaa</value>
            <value>ddddd</value>
        </list>
    </util:property>
    <util:property>
        <list>
            <ref bean = "anotherBean"/>
            <ref bean = "anotherBean"/>
        </list>
    </util:property>
    <util:propertiy name="properties">
        <prop key="aaaaa">bbbbb</prop>
    </util:propertiy>

class005Test.java

        Bean bean = context.getBean("bean",Bean.class);
        System.out.println("bean.getStringList() = " + bean.getSring());
        System.out.println("bean.getProperties() = " + bean.getProperties());

在这里插入图片描述
在这里插入图片描述

null注入

Bean.java

    public AnotherBean getAnotherBean2() {
        return anotherBean2;
    }

    public void setAnotherBean2(AnotherBean anotherBean2) {
        this.anotherBean2 = anotherBean2;
    }

    private AnotherBean anotherBean2;

spring.xml

    <util:properties name = "anotherBean2">
        <null/>
    </util:properties>

class005Test.java

System.out.println("bean.getAnotherBean2()" + bean.getAnotherBean2());

在这里插入图片描述

注入的时候创建内部Bean
    <util:properties>
        <bean class = "com.example.controller.AnotherBean"/>
    </util:properties>

在这里插入图片描述

Bean的作用域的问题

  • Sinleton作用域

  • prototype作用域

  • Web环境作用域

    • requset
    • session
    • application
    • websocket
  • 自定义作用域

    • SimpleThreadScope作用域
Singleton作用域(单例模式)

在这里插入图片描述
右侧的Bean会通过Spring注入左侧三个Bean中 只会创建一个Bean

Bean.java

public class Bean {

    public Beanb getBeanb() {
        return beanb;
    }

    public void setBeanb(Beanb beanb) {
        this.beanb = beanb;
    }

    private Beanb beanb;

    @Override
    public String toString() {
        return "Bean{" +
                "beanb=" + beanb +
                '}';
    }
}

spring.xml

    <bean class = "com.example.controller.People.Beanb" id = "bean2"
        scope="prototype"/>

    <bean class = "com.example.controller.People.Bean" id = "bean"
    scope="prototype">
        <property name="beanb" ref="bean2"></property>
    </bean>

public class Class007Test {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Beanb bean2_1 = context.getBean("Beanb",Beanb.class);
    System.out.println("bean2_1 = " + bean2_1);
    Beanb bean2_2 = context.getBean("bean2_2 = " + bean2_2);
    System.out.println("bean2_2 = " bean2_2);
    bean bean1 = context.getBean("bean",Bean.class);
    System.out.println("bean = " + bean);
}

在这里插入图片描述
在这里插入图片描述

Prototype作用域(多例模式)

在这里插入图片描述

在这里插入图片描述

Web相关作用域

  • requset作用域
  • sessiong作用域
  • applicatiton作用域
  • websocker作用域(很少使用)

SpringWeb上下文环境

如果使用DispatcherServlet 不需要增加其他配置

在这里插入图片描述

web.xml
在这里插入图片描述
RequsetController.java
在这里插入图片描述
spring.xml

<bean class="com.spring.ioc.class08.RequestController"/>
<bean class="com.spring.ioc.class08.SessionController"/>
<bean class="com.spring.ioc.class08.ApplicationController"/>

在这里插入图片描述
每次刷新@contraller不变

<bean class="com.spring.ioc.class08.RequestController" scope = "requset"/>
<bean class="com.spring.ioc.class08.SessionController" scope = "requset"/>
<bean class="com.spring.ioc.class08.ApplicationController" scope = "requset"/>

每次刷新@contraller改变
回顾

  • request:每个requset请求斗湖创建一个单独的实例
  • session:每个session都会创建一个单独的实例
  • application:每个servletContext都会创建一个单独的实例
  • websocket:每个websocket链接都会创建一个单独实例
自定义作用域
  • SimpleThreadScope作用域

MyScope.java
在这里插入图片描述
spring.xml


Bean的懒加载

Spring容器会在创建容器时提前初始化Singleton作用域的bean
但如果Bean被标记了lazy-init = “true”
那么该Bean只有在其被需要的时候才会初始化

只对singleton作用域的bean有效
多例模式不知道bean什么时候被实例化

单一的Bean需要懒加载

    <bean class = "com.example.controller.People.Beanb" id = "bean2"
        scope="singleton" lazy-init="true"/>

所有的bean需要懒加载

<beans default-lazy-init="true">

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
位所有的bean都设置默认的
在这里插入图片描述

Bean初始化及销毁逻辑处理

如果Bean实例化之后执行一些逻辑 有两种方法

  • bean标签里的属性 initmethod
  • 让Bean实现InitializingBean接口

如果Bean在销毁之前需要执行一些逻辑 两种方法

  • destory-method
  • DisposableBean接口

Bean属性继承

场景1
在这里插入图片描述
简化代码
在这里插入图片描述
场景2
在这里插入图片描述
在这里插入图片描述

注解

spring2.5之后用注解取代xml

xml 与 annotation对比

在这里插入图片描述
MyConfiguration.java

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

@Configuration
public class MyConfiguration {

    @Bean //这里也可以用(value=“bean1命名”)
    public Bean bean1(){
        return new Bean();
    }
}

Test.java

import com.example.controller.People.MyConfiguration;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Class008Test {
    
    @Test
    public void test(){
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        Bean1 bean1 = context.getBean("bean",Bean.class);
        System.out.println("bean1 = " + bean1);
    }
}

在这里插入图片描述

简化代码

conpoent-scan包扫描
在这里插入图片描述
@ component注解
在这里插入图片描述

给Bean取别名

在这里插入图片描述

通过注解注入Bean

在这里插入图片描述
构造方法和Set方法注入Bean
在这里插入图片描述
通过属性直接注入
在这里插入图片描述
实例化和注入时指定Bean的id
在这里插入图片描述
List/Set注入
直接注入List实例
在这里插入图片描述
将多个泛型实例注入到List
在这里插入图片描述
Map注入
在这里插入图片描述
多个泛型实例注入Map
在这里插入图片描述
String Integer类型的直接赋值
在这里插入图片描述
Spring Ioc容器内置借口实例注入
在这里插入图片描述
可以直接将ApplicationContext注入进来,也可以注入BeanFactory、Environment、ResourceLoader、ApplicationEventPublisher\MessagerSource及其实现类

SpringIoc注解设定Scope(作用域)

Spring预定义作用域
在这里插入图片描述
自定义作用域
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方法注入
在这里插入图片描述
在这里插入图片描述

通过注解开启Bean的懒加载

在这里插入图片描述

通过注解编写Bean初始化及销毁

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oifengo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值