实验一 -配置和获取
1.实验目标和思路
2、创建Maven Module
<dependencies><!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.1</version></dependency><!-- junit测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies>
3、创建组件类
package com.atguigu.ioc.component;public class HappyComponent {public void doWork() {System.out.println("component do work ...");}}
4、创建 Spring 配置文件
5、配置组件
<!-- 实验一 [重要]创建bean --><bean id="happyComponent" class="com.atguigu.ioc.component.HappyComponent"/>
- bean标签:通过配置bean标签告诉IOC容器需要创建对象的组件是什么
- id属性:bean的唯一标识
-
6、创建测试类
```java 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();}
}
<a name="roaHn"></a>
## 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.<init>()
>
<a name="p8gf2"></a>
# 实验二 -根据类类型获取bean
<a name="DHpte"></a>
## 1、方式一:根据id获取
由于 id 属性指定了 bean 的唯一标识,所以根据 bean 标签的 id 属性可以精确获取到一个组件对象。上个实验中我们使用的就是这种方式。
<a name="VVgjy"></a>
## 2、方式二:根据类型获取
<a name="gI8bZ"></a>
### ①指定类型的 bean 唯一
```java
@Test
public void testExperiment02() {
HappyComponent component = iocContainer.getBean(HappyComponent.class);
component.doWork();
}
②指定类型的 bean 不唯一
相同类型的 bean 在IOC容器中一共配置了两个:
<!-- 实验一 [重要]创建bean -->
<bean id="happyComponent" class="com.atguigu.ioc.component.HappyComponent"/>
<!-- 实验二 [重要]获取bean -->
<bean id="happyComponent2" class="com.atguigu.ioc.component.HappyComponent"/>
根据类型获取时会抛出异常:
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方式验证一下
<bean id="happyComponent3" class="com.atguigu.ioc.component.HappyComponent">
<!-- property标签:通过组件类的setXxx()方法给组件对象设置属性 -->
<!-- name属性:指定属性名(这个属性名是getXxx()、setXxx()方法定义的,和成员变量无关) -->
<!-- value属性:指定属性值 -->
<property name="componentName" value="veryHappy"/>
</bean>
实验四 [重要]给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
<bean id="happyMachine" class="com.atguigu.ioc.component.HappyMachine">
<property name="machineName" value="makeHappy"/>
</bean>
4、在原组件的 bean 中引用新组件的 bean
<bean id="happyComponent4" class="com.atguigu.ioc.component.HappyComponent">
<!-- ref 属性:通过 bean 的 id 引用另一个 bean -->
<property name="happyMachine" ref="happyMachine"/>
</bean>
5、易错点
如果错把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内部使用,在其他地方不能使用。
<!-- 实验五 [重要]给bean的属性赋值:内部bean -->
<bean id="happyComponent5" class="com.atguigu.ioc.component.HappyComponent">
<property name="happyMachine">
<!-- 在一个 bean 中再声明一个 bean 就是内部 bean -->
<!-- 内部 bean 可以直接用于给属性赋值,可以省略 id 属性 -->
<bean class="com.atguigu.ioc.component.HappyMachine">
<property name="machineName" value="makeHappy"/>
</bean>
</property>
</bean>
实验六 [重要]给bean的属性赋值:引入外部属性文件
1、加入依赖
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.3</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
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、引入
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
4、使用
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
注意是driverClassName!!!!!
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
<bean id="happyMachine2" class="com.atguigu.ioc.component.HappyMachine"/>
2、装配关联对象并赋值级联属性
关联对象:happyMachine
级联属性:happyMachine.machineName
<!-- 实验七 给bean的属性赋值:级联属性赋值 -->
<bean id="happyComponent6" class="com.atguigu.ioc.component.HappyComponent">
<!-- 装配关联对象 -->
<property name="happyMachine" ref="happyMachine2"/>
<!-- 对HappyComponent来说,happyMachine的machineName属性就是级联属性 -->
<property name="happyMachine.machineName" value="cascadeValue"/>
</bean>
实验八 给bean的属性赋值:构造器注入
配置
<!-- 实验八 给bean的属性赋值:构造器注入 -->
<bean id="happyTeam" class="com.atguigu.ioc.component.HappyTeam">
<constructor-arg value="happyCorps"/>
<constructor-arg value="10"/>
<constructor-arg value="1000.55"/>
</bean>


