栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

第三节 基于XML管理bean(第一章)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第三节 基于XML管理bean(第一章)

第三节 基于XML管理bean(第一章)

文章目录
  • 第三节 基于XML管理bean(第一章)
  • 实验一 [重要]创建bean
    • 1、实验目标和思路
      • ①目标
      • ②思路
    • 2、创建Maven Module
    • 3、创建组件类
    • 4、创建 Spring 配置文件
    • 5、配置组件
    • 6、创建测试类
    • 7、无参构造器
    • 8、用IOC容器创建对象和自己建区别
  • 实验二 [重要]获取bean
    • 1、方式一:根据id获取
    • 2、方式二:根据类型获取
      • ①指定类型的 bean 唯一
      • ②指令类型的 bean 不唯一
      • ③思考
      • ④结论
  • 实验三 [重要]给bean的属性赋值:setter注入
    • 1、给组件类添加一个属性
    • 2、在配置时给属性指定值
    • 3、测试
  • 实验四 [重要]给bean的属性赋值:引用外部已声明的bean
    • 1、声明新的组件类
    • 2、原组件引用新组件
    • 3、配置新组件的 bean
    • 4、在原组件的 bean 中引用新组件的 bean
    • 5、测试
    • 6、易错点
  • 实验五 [重要]给bean的属性赋值:内部bean
    • 1、重新配置原组件
    • 2、测试
  • 实验六 [重要]给bean的属性赋值:引入外部属性文件
    • 1、加入依赖
    • 2、创建外部属性文件
    • 3、引入
    • 4、使用
    • 5、测试
  • 实验七 给bean的属性赋值:级联属性赋值
    • 1、配置关联对象的 bean
    • 2、装配关联对象并赋值级联属性
    • 3、测试
  • 实验八 给bean的属性赋值:构造器注入
    • 1、声明组件类
    • 2、配置
    • 3、测试
    • 4、补充
  • 实验九 给bean的属性赋值:特殊值处理
    • 1、声明一个类用于测试
    • 2、字面量
      • ①用Java代码举例说明
      • ②Spring配置文件中举例
        • [1]字面量举例
        • [2]类似变量举例
    • 3、null值
    • 4、XML实体
    • 5、CDATA节
  • 实验十 给bean的属性赋值:使用p名称空间
    • 1、配置
    • 2、测试
  • 实验十一 给bean的属性赋值:集合属性
    • 1、给组件类添加属性
    • 2、配置
    • 3、测试
    • 4、其他变化形式
  • 实验十二 自动装配
    • 1、声明组件类
    • 2、配置
    • 3、测试
  • 实验十三 集合类型的bean
    • 1、配置
    • 2、测试
  • 实验十四 FactoryBean机制
    • 1、简介
    • 2、实现FactoryBean接口
    • 3、配置bean
    • 4、测试获取bean
  • 实验十五 bean的作用域
    • 1、概念
    • 2、配置
    • 3、测试
  • 实验十六 bean的生命周期
    • 1、bean的生命周期清单
    • 2、指定bean的初始化方法和销毁方法
      • ①创建两个方法作为初始化和销毁方法
      • ②配置bean时指定初始化和销毁方法
    • 3、bean的后置处理器
      • ①创建后置处理器类
      • ②把bean的后置处理器放入IOC容器
      • ③执行效果示例
    • 3、bean的后置处理器
      • ①创建后置处理器类
      • ②把bean的后置处理器放入IOC容器
      • ③执行效果示例

实验一 [重要]创建bean 1、实验目标和思路 ①目标

由 Spring 的 IOC 容器创建类的对象。

②思路

2、创建Maven Module

    
    
        org.springframework
        spring-context
        5.3.1
    
    
    
        junit
        junit
        4.12
        test
    

3、创建组件类
package com.atguigu.ioc.component;
    
public class HappyComponent {
    
    public void doWork() {
        System.out.println("component do work ...");
    }
    
}
4、创建 Spring 配置文件


5、配置组件



  • bean标签:通过配置bean标签告诉IOC容器需要创建对象的组件是什么
  • id属性:bean的唯一标识
  • class属性:组件类的全类名
6、创建测试类
public class IOCTest {
    
    // 创建 IOC 容器对象,为便于其他实验方法使用声明为成员变量
    private ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    @Test
    public void testExperiment01() {
    
        // 从 IOC 容器对象中获取bean,也就是组件对象
        HappyComponent happyComponent = (HappyComponent) iocContainer.getBean("happyComponent");
    
        happyComponent.doWork();
    
    }
    
}
7、无参构造器

Spring 底层默认通过反射技术调用组件类的无参构造器来创建组件对象,这一点需要注意。如果在需要无参构造器时,没有无参构造器,则会抛出下面的异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘happyComponent1’ defined in class path resource [applicationContext.xml]: Instantiation of bean failed;

nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.atguigu.ioc.component.HappyComponent]: No default constructor found;

nested exception is java.lang.NoSuchMethodException: com.atguigu.ioc.component.HappyComponent.()

所以对一个JavaBean来说,无参构造器和属性的getXxx()、setXxx()方法是必须存在的,特别是在框架中。

8、用IOC容器创建对象和自己建区别

在Spring环境下能够享受到的所有福利,都必须通过 IOC 容器附加到组件类上,所以随着我们在 Spring 中学习的功能越来越多,IOC 容器创建的组件类的对象就会比自己 new 的对象强大的越来越多。

实验二 [重要]获取bean

1、方式一:根据id获取

由于 id 属性指定了 bean 的唯一标识,所以根据 bean 标签的 id 属性可以精确获取到一个组件对象。上个实验中我们使用的就是这种方式。

2、方式二:根据类型获取 ①指定类型的 bean 唯一
@Test
public void testExperiment02() {
    
    HappyComponent component = iocContainer.getBean(HappyComponent.class);
    
    component.doWork();
    
}
②指令类型的 bean 不唯一

相同类型的 bean 在IOC容器中一共配置了两个:






根据类型获取时会抛出异常:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.atguigu.ioc.component.HappyComponent’ available: expected single matching bean but found 2: happyComponent,happyComponent2

③思考

如果组件类实现了接口,根据接口类型可以获取 bean 吗?

可以,前提是bean唯一

如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型可以获取 bean 吗?

不行,因为bean不唯一

④结论

根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象 instanceof 指定的类型』的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。

实验三 [重要]给bean的属性赋值:setter注入 1、给组件类添加一个属性
public class HappyComponent {
    
    private String componentName;
    
    public String getComponentName() {
        return componentName;
    }
    
    public void setComponentName(String componentName) {
        this.componentName = componentName;
    }
    
    public void doWork() {
        System.out.println("component do work ...");
    }
    
}
2、在配置时给属性指定值

通过property标签配置的属性值会通过setXxx()方法注入,大家可以通过debug方式验证一下



    
    
    
    
    

3、测试
@Test
public void testExperiment03() {
    
    HappyComponent happyComponent3 = (HappyComponent) iocContainer.getBean("happyComponent3");
    
    String componentName = happyComponent3.getComponentName();
    
    System.out.println("componentName = " + componentName);
    
}
实验四 [重要]给bean的属性赋值:引用外部已声明的bean 1、声明新的组件类
public class HappyMachine {
    
    private String machineName;
    
    public String getMachineName() {
        return machineName;
    }
    
    public void setMachineName(String machineName) {
        this.machineName = machineName;
    }
}
2、原组件引用新组件

3、配置新组件的 bean

    
4、在原组件的 bean 中引用新组件的 bean

    
    

这个操作在 IDEA 中有提示:

5、测试
@Test
public void testExperiment04() {
    HappyComponent happyComponent4 = (HappyComponent) iocContainer.getBean("happyComponent4");
    
    HappyMachine happyMachine = happyComponent4.getHappyMachine();
    
    String machineName = happyMachine.getMachineName();
    
    System.out.println("machineName = " + machineName);
}
6、易错点

如果错把ref属性写成了value属性,会抛出异常:
Caused by: java.lang.IllegalStateException: Cannot convert value of type ‘java.lang.String’ to required type ‘com.atguigu.ioc.component.HappyMachine’ for property ‘happyMachine’: no matching editors or conversion strategy found
意思是不能把String类型转换成我们要的HappyMachine类型
说明我们使用value属性时,Spring只把这个属性看做一个普通的字符串,不会认为这是一个bean的id,更不会根据它去找到bean来赋值

实验五 [重要]给bean的属性赋值:内部bean 1、重新配置原组件

在bean里面配置的bean就是内部bean,内部bean只能在当前bean内部使用,在其他地方不能使用。



    
        
        
        
            
        
    

2、测试
@Test
public void testExperiment04() {
    HappyComponent happyComponent4 = (HappyComponent) iocContainer.getBean("happyComponent4");
    
    HappyMachine happyMachine = happyComponent4.getHappyMachine();
    
    String machineName = happyMachine.getMachineName();
    
    System.out.println("machineName = " + machineName);
}
实验六 [重要]给bean的属性赋值:引入外部属性文件 1、加入依赖
        
        
            mysql
            mysql-connector-java
            5.1.3
        
        
        
            com.alibaba
            druid
            1.0.31
        
2、创建外部属性文件

jdbc.user=root
jdbc.password=atguigu
jdbc.url=jdbc:mysql://192.168.198.100:3306/mybatis-example
jdbc.driver=com.mysql.jdbc.Driver
3、引入
    
    
4、使用


    
    
    
    

5、测试
@Test
public void testExperiment06() throws SQLException {
    DataSource dataSource = iocContainer.getBean(DataSource.class);

    Connection connection = dataSource.getConnection();

    System.out.println("connection = " + connection);
}
实验七 给bean的属性赋值:级联属性赋值 1、配置关联对象的 bean

2、装配关联对象并赋值级联属性

关联对象:happyMachine

级联属性:happyMachine.machineName



    
    
    
    

3、测试
@Test
public void testExperiment07() {
    
    HappyComponent happyComponent6 = (HappyComponent) iocContainer.getBean("happyComponent6");
    
    String machineName = happyComponent6.getHappyMachine().getMachineName();
    
    System.out.println("machineName = " + machineName);

}
实验八 给bean的属性赋值:构造器注入 1、声明组件类
package com.atguigu.ioc.component;
    
public class HappyTeam {
        
    private String teamName;
    private Integer memberCount;
    private Double memberSalary;
    
    public String getTeamName() {
        return teamName;
    }
    
    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }
    
    public Integer getMemberCount() {
        return memberCount;
    }
    
    public void setMemberCount(Integer memberCount) {
        this.memberCount = memberCount;
    }
    
    public Double getMemberSalary() {
        return memberSalary;
    }
    
    public void setMemberSalary(Double memberSalary) {
        this.memberSalary = memberSalary;
    }
    
    @Override
    public String toString() {
        return "HappyTeam{" +
                "teamName='" + teamName + ''' +
                ", memberCount=" + memberCount +
                ", memberSalary=" + memberSalary +
                '}';
    }
    
    public HappyTeam(String teamName, Integer memberCount, Double memberSalary) {
        this.teamName = teamName;
        this.memberCount = memberCount;
        this.memberSalary = memberSalary;
    }
    
    public HappyTeam() {
    }
}
2、配置


    
    
    

3、测试
@Test
public void testExperiment08() {
    
    HappyTeam happyTeam = iocContainer.getBean(HappyTeam.class);
    
    System.out.println("happyTeam = " + happyTeam);
    
}
4、补充

constructor-arg标签还有两个属性可以进一步描述构造器参数:

  • index属性:指定参数所在位置的索引(从0开始)
  • name属性:指定参数名
实验九 给bean的属性赋值:特殊值处理 1、声明一个类用于测试
package com.atguigu.ioc.component;
    
public class PropValue {
    
    private String commonValue;
    private String expression;
    
    public String getCommonValue() {
        return commonValue;
    }
    
    public void setCommonValue(String commonValue) {
        this.commonValue = commonValue;
    }
    
    public String getExpression() {
        return expression;
    }
    
    public void setExpression(String expression) {
        this.expression = expression;
    }
    
    @Override
    public String toString() {
        return "PropValue{" +
                "commonValue='" + commonValue + ''' +
                ", expression='" + expression + ''' +
                '}';
    }

    public PropValue(String commonValue, String expression) {
        this.commonValue = commonValue;
        this.expression = expression;
    }

    public PropValue() {
    }
}
2、字面量 ①用Java代码举例说明

字面量是相对于变量来说的。看下面的代码:

int a = 10;

声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字。当我们引用a的时候,我们实际上拿到的值是10。

而如果a是带引号的:‘a’,那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量。所以字面量没有引申含义,就是我们看到的这个数据本身。

②Spring配置文件中举例 [1]字面量举例


[2]类似变量举例



3、null值
        
            
            
        
4、XML实体


    
    
    

5、CDATA节


    
        
        
        
        
        
    

实验十 给bean的属性赋值:使用p名称空间 1、配置

使用 p 名称空间的方式可以省略子标签 property,将组件属性的设置作为 bean 标签的属性来完成。



使用 p 名称空间需要导入相关的 XML 约束,在 IDEA 的协助下导入即可:



具体操作时,输入p:稍微等一下,等IDEA弹出下面的提示:

按Alt+Enter即可导入。

2、测试
@Test
public void testExperiment10() {
    HappyMachine happyMachine3 = (HappyMachine) iocContainer.getBean("happyMachine3");
    
    String machineName = happyMachine3.getMachineName();
    
    System.out.println("machineName = " + machineName);
}
实验十一 给bean的属性赋值:集合属性 1、给组件类添加属性

2、配置


    
        
            member01
            member02
            member03
        
    

3、测试
@Test
public void testExperiment13() {
    
    HappyTeam happyTeam2 = (HappyTeam) iocContainer.getBean("happyTeam2");
    
    List memberList = happyTeam2.getMemberList();
    
    for (String member : memberList) {
        System.out.println("member = " + member);
    }
    
}
4、其他变化形式


    
        
        
        
        
        
        
            member01
            member02
            member02
        
    
    
        
        
        
        
            张三2
            李四2
            王五2
        
    

实验十二 自动装配 1、声明组件类

其中HappyController需要用到HappyService。所谓自动装配就是一个组件需要其他组件时,由 IOC 容器负责找到那个需要的组件,并装配进去。

public class HappyController {
        
    private HappyService happyService;
    
    public HappyService getHappyService() {
        return happyService;
    }
    
    public void setHappyService(HappyService happyService) {
        this.happyService = happyService;
    }
}
public class HappyService {
}
2、配置








    
    

3、测试
@Test
public void testExperiment12() {
    HappyController happyController = iocContainer.getBean(HappyController.class);
    
    HappyService happyService = happyController.getHappyService();
    
    System.out.println("happyService = " + happyService);
}
实验十三 集合类型的bean 1、配置


    
        
    
    
        
    
    
        
    

2、测试
@Test
public void testExperiment11() {
    List machineList = (List) iocContainer.getBean("machineList");
    for (HappyMachine happyMachine : machineList) {
        System.out.println("happyMachine = " + happyMachine);
    }
}
实验十四 FactoryBean机制 1、简介

FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。

将来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的。


package org.springframework.beans.factory;

import org.springframework.lang.Nullable;


public interface FactoryBean {

	
	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";


	
	@Nullable
	T getObject() throws Exception;

	
	@Nullable
	Class getObjectType();

	
	default boolean isSingleton() {
		return true;
	}

}
2、实现FactoryBean接口 3、配置bean 4、测试获取bean 实验十五 bean的作用域 1、概念

在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围,各取值含义参加下表:

取值含义创建对象的时机
singleton在IOC容器中,这个bean的对象始终为单实例IOC容器初始化时
prototype这个bean在IOC容器中有多个实例获取bean时

如果是在WebApplicationContext环境下还会有另外两个作用域(但不常用):

取值含义
request在一个请求范围内有效
session在一个会话范围内有效
2、配置




    

3、测试
@Test
public void testExperiment15() {
    HappyMachine happyMachine01 = (HappyMachine) iocContainer.getBean("happyMachine4");
    HappyMachine happyMachine02 = (HappyMachine) iocContainer.getBean("happyMachine4");
    
    System.out.println(happyMachine01 == happyMachine02);
    
    System.out.println("happyMachine01.hashCode() = " + happyMachine01.hashCode());
    System.out.println("happyMachine02.hashCode() = " + happyMachine02.hashCode());
}
实验十六 bean的生命周期 1、bean的生命周期清单
  • bean对象创建(调用无参构造器)
  • 给bean对象设置属性
  • bean对象初始化之前操作(由bean的后置处理器负责)
  • bean对象初始化(需在配置bean时指定初始化方法)
  • bean对象初始化之后操作(由bean的后置处理器负责)
  • bean对象就绪可以使用
  • bean对象销毁(需在配置bean时指定销毁方法)
  • IOC容器关闭
2、指定bean的初始化方法和销毁方法 ①创建两个方法作为初始化和销毁方法

用com.atguigu.ioc.component.HappyComponent类测试:

public void happyInitMethod() {
    System.out.println("HappyComponent初始化");
}
    
public void happyDestroyMethod() {
    System.out.println("HappyComponent销毁");
}
②配置bean时指定初始化和销毁方法




    

3、bean的后置处理器 ①创建后置处理器类
package com.atguigu.ioc.process;
    
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
    
// 声明一个自定义的bean后置处理器
// 注意:bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行
public class MyHappyBeanProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
        System.out.println("☆☆☆" + beanName + " = " + bean);
    
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
        System.out.println("★★★" + beanName + " = " + bean);
    
        return bean;
    }
}
②把bean的后置处理器放入IOC容器


③执行效果示例

HappyComponent创建对象
HappyComponent要设置属性了
☆☆☆happyComponent = com.atguigu.ioc.component.HappyComponent@ca263c2
HappyComponent初始化
★★★happyComponent = com.atguigu.ioc.component.HappyComponent@ca263c2
HappyComponent销毁

ethod=“happyDestroyMethod”


``` 3、bean的后置处理器 ①创建后置处理器类
package com.atguigu.ioc.process;
    
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
    
// 声明一个自定义的bean后置处理器
// 注意:bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行
public class MyHappyBeanProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
        System.out.println("☆☆☆" + beanName + " = " + bean);
    
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
        System.out.println("★★★" + beanName + " = " + bean);
    
        return bean;
    }
}
②把bean的后置处理器放入IOC容器


③执行效果示例

HappyComponent创建对象
HappyComponent要设置属性了
☆☆☆happyComponent = com.atguigu.ioc.component.HappyComponent@ca263c2
HappyComponent初始化
★★★happyComponent = com.atguigu.ioc.component.HappyComponent@ca263c2
HappyComponent销毁

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/877807.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号