实验1:通过IOC容器创建对象,并为属性赋值★
实验2:根据bean的类型从IOC容器中获取bean的实例★
如果IOC容器这个类型的bean有多个,查找会报错
报错org.springframework.beans.factory.NoUniqueBeanDefinitionException
1 | /*Person bean = ioc.getBean(Person.class); |
实验3:
- 通过构造器为bean的属性赋值(index,type属性介绍)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<!-- 必须为Person创建全参构造 -->
<!-- 方法一 -->
<bean id="person01" class="xyz.lyhcc.bean.Person">
<constructor-arg name="lastName" value="KL"></constructor-arg>
<constructor-arg name="name" value="KJJJL"></constructor-arg>
<constructor-arg name="gender" value="F"></constructor-arg>
<constructor-arg name="email" value="KL@123.com"></constructor-arg>
</bean>
<!-- 方法二 -->
<!-- 注意:下面的顺序必须按照构造函数的参数顺序,但可以使用index指定 -->
<bean id="person01" class="xyz.lyhcc.bean.Person">
<constructor-arg value="KL1"></constructor-arg>
<constructor-arg value="KJJ1JL"></constructor-arg>
<constructor-arg value="M"></constructor-arg>
<constructor-arg value="KLw@123.com"></constructor-arg>
</bean>
<!-- 构造函数重载时,如果需要指定调用,可以使用type="java.lang.Integer" --> - 通过p名称空间为bean赋值,导入p命名空间
1
2
3
4
5
6
7<!-- 名称控件是用来防止标签重复的 -->
<!-- 1)导入命名空间 2)写带前缀的标签 -->
xmlns:p="http://www.springframework.org/schema/p"
<!-- 遇到的问题:在对应的spring configuration xml中没有namespace选项,将文件关掉,点击explore上面找到对应的配置文件,右键->open with ->spring config editor -->
<bean id="person01" class="xyz.lyhcc.bean.Person"
p:gender="F" p:email="abc@123.com" p:lastName="AC" p:name="CB">
</bean>实验4:正确的为各种属性赋值
- 测试使用null值
1
2
3
4
5
6
7<!-- 默认不赋值也为null -->
<bean id="person01" class="xyz.lyhcc.bean.Person">
<property name="lastName">
<!-- 复杂标签赋值 -->
<null></null>
</property>
</bean> - 引用类型赋值(引用其他bean、引用内部bean)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<!-- 为Person类增加一个Person属性,并生成getter/setteer方法 -->
<!-- 引用外部 -->
<bean id="person01" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="李四"></property>
<property name="name" value="王五"></property>
<property name="gender" value="男"></property>
<property name="email" value="abc@123.com"></property>
</bean>
<bean id="person02" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="AS"></property>
<property name="name" value="QW"></property>
<property name="gender" value="F"></property>
<property name="email" value="abcds@123.com"></property>
<property name="person" ref="person01"></property>
</bean>
<!-- 内部 说明:内部bean不能直接获取 -->
<bean id="person02" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="AS"></property>
<property name="name" value="QW"></property>
<property name="gender" value="F"></property>
<property name="email" value="abcds@123.com"></property>
<property name="person">
<bean id="person01" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="李四"></property>
<property name="name" value="王五"></property>
<property name="gender" value="男"></property>
<property name="email" value="abc@123.com"></property>
</bean>
</property>
</bean> - 集合类型赋值(List、Map、Properties)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53<!-- List -->
<!-- Person添加friends属性 -->
<bean id="person01" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="李四"></property>
<property name="name" value="王五"></property>
<property name="gender" value="男"></property>
<property name="email" value="abc@123.com"></property>
</bean>
<bean id="person02" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="AS"></property>
<property name="name" value="QW"></property>
<property name="gender" value="F"></property>
<property name="email" value="abcds@123.com"></property>
<property name="friends">
<list>
<bean class="xyz.lyhcc.bean.Person" p:lastName="AC" p:email="as@123.com"></bean>
<ref bean="person01"/>
</list>
</property>
</bean>
<!-- Map -->
<!-- Person中添加map属性 -->
<bean id="person02" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="AS"></property>
<property name="name" value="QW"></property>
<property name="gender" value="F"></property>
<property name="email" value="abcds@123.com"></property>
<property name="map">
<!-- new LinkedHashMap -->
<map>
<entry key="A" value="1"></entry>
<entry key="B" value="2"></entry>
<entry key="D" value="3"></entry>
<entry key="C" value="4"></entry>
</map>
</property>
</bean>
<!-- Properties -->
<!-- 在Person中添加Properties属性 -->
<bean id="person02" class="xyz.lyhcc.bean.Person">
<property name="lastName" value="AS"></property>
<property name="name" value="QW"></property>
<property name="gender" value="F"></property>
<property name="email" value="abcds@123.com"></property>
<property name="properties">
<!-- new Properties() -->
<props>
<prop key="username">WSX</prop>
<prop key="passwd">AS</prop>
</props>
</property>
</bean>
util名称空间创建集合类型的bean
1
2
3
4
5
6
7
8<!-- util名称空间创建集合的bean,方便引用 -->
<util:map id="myMap">
<entry key="A" value="1"></entry>
<entry key="B" value="2"></entry>
<entry key="C" value="3"></entry>
<entry key="D" value="4"></entry>
</util:map>
<util:list id="mylist"></util:list>级联属性赋值(级联属性表示属性的属性)
====================工厂方式创建bean==========
实验5:配置通过静态工厂方法创建的bean、实例工厂方法创建的bean、FactoryBean★
1 | <!-- 使用Book类,里面有name,author,price三个属性,并生成getter/setter方法 --> |
1 | <!-- FactoryBean 是Spring规定的一个接口,只要这个接口的实现类, Spring都认为是一个工厂,Spring会自动调用工厂方法 |
实验6:通过继承实现bean配置信息的重用
1 | <bean id="person01" class="xyz.lyhcc.bean.Person"> |
实验7:通过abstract属性创建一个模板bean
1 | 无法获取报异常 org.springframework.beans.factory.BeanIsAbstractException |
实验8:bean之间的依赖
1 | <!-- 默认是按照配置文件的顺序创建 --> |
实验9:测试bean的作用域,分别创建单实例和多实例的bean★
1 | <!-- bean的作用域:指定bean是否为单实例,默认单实例 --> |
实验10:创建带有生命周期方法的bean
生命周期:bean的创建到销毁
- 单例Bean, 容器启动的时候就会创建好,容器关闭也会销毁创建的bean
- 多实例bean, 获取的时候才创建
自定义一些生命周期的方法,spring在创建或者销毁的时候就会调用指定的方法
自定义初始化方法和销毁方法,可以抛任意异常,但不能有参数
Bean的生命周期
- 单实例:构造器–>初始化方法–>(容器关闭)销毁方法
- 多实例:获取bean(构造器–>初始化方法)–>容器关闭不会调用bean的销毁方法
1 | <bean id="book04" class="xyz.lyhcc.bean.Book" init-method="init" destroy-method="destory"></bean> |
实验11:测试bean的后置处理器
Spring有一个接口(BeanPostProcessor);后置处理器,可以在bean初始化前调用 初始化方法, 后置处理器可以干扰初始化
无论bean是否有初始化方法,后置处理器都会默认有,并继续执行
BeanPostProcessor 有两个抽象方法
postProcessBeforeInitialization 初始化之前调用
postProcessAfterInitialization 初始化之后调用
使用方法
- 编写后置处理器的实现类
- 将后置处理器注册在配置文件中
1 | // beanName是在bean配置文件中的id |
实验12:引用外部属性文件★
1 | <!-- 数据库连接池作为单实例是最好的,一个项目一个池,管理多个连接,连接从连接池中获取,可以让Spring创建连接池对象 --> |

注意:
使用时需要三个jar包, c3p0、mchange、mysql
1 | mchange-commons-java-0.2.11.jar |
org.springframework.beans.factory.BeanCreationException:
出现这个问题是需要一个包,具体参考
实验13:基于XML的自动装配(自定义类型自动赋值)
JavaBean(基本类型)
(自定义类型是一个对象,这个对象可能存在容器中)
自动装配:
1 | autowire="default/no", 不自动装配 |
实验14:[SpEL(Spring Expression Language)测试I]
- 在SpEL中使用字面量
- 引用其他bean
- 引用其他bean的某个属性值
- 调用非静态方法
- 调用静态方法
- 使用运算符
1
2
3
4
5
6
7
8
9
10
11
12
13<bean id="person01" class="xyz.lyhcc.bean.Person">
<!-- 字面量 和使用运算符 -->
<property name="age" value="#{12*3}"></property>
<!-- 引用其他bean -->
<property name="person" value="#{person02}"></property>
<!-- 应用其他bean的属性值 -->
<property name="lastName" value="#{person02.lastName}"></property>
<!-- 非静态方法的调用 -->
<property name="name" value="#{person02.getName()}"></property>
<!-- 静态方法调用#{T(类名).静态方法} -->
<property name="email" value="#{T(java.util.UUID).randomUUID().toString()}"></property>
</bean>
实验15:通过注解分别创建Dao、Service、Controller(控制器,控制网站跳转逻辑Servlet)★
通过给bean上添加注解,可以快速的将bean加入ioc容器中
Spring的四个注解添加任何一个注解都能快速将这个组件注册到ioc容器中
- @Controller 控制器 我们推荐给控制层的组件(Servlet)添加这个注解
- @Service 业务逻辑,我们推荐业务逻辑层的组件添加这个注解,
- @Resposity 给持久化层组件添加这个注解(Dao层)
- @Component 不属于以上几层组件
注意: Spring底层不会去验证你的这个组件,是否如你所说的是一个Servlet层或者Dao层组件
使用注解快速添加组件到容器需要几步
- 添加注释(四个的一个)
- 告诉Spring,自动扫描加了注释的组件,依赖context命名空间
<context:component-scan base-package=””>
base-package 指定扫描的基础包 把基础包及他下面所有加了注释的类,自动注册到ioc容器中- 导入aop包之后才会支持注解,否则报异常org.springframework.beans.factory.BeanDefinitionStoreException:
使用注解加入到容器中的组件,和使用配置加入到容器中的㢟行为都是默认一样的
- 组件的id,默认就是类名首字母小写
@Repository(“bookdao123”)
- 组件的作用域,默认是单例
@Scope(value=”prototype”)
1 | <!-- Dao层(数据库访问)、Service层(业务处理)、Web层(页面控制action类) --> |
实验16:使用context:include-filter指定扫描包时要包含的类
使用需禁用默认规则use-default-filters="false"1 | <context:component-scan base-package="xyz.lyhcc" use-default-filters="false"> |
实验17:使用context:exclude-filter指定扫描包时不包含的类
type="annotation" 指定排除规则,按照注解进行排除,标注了指定注解组件不需要
expression="" 注解的全类名 如 org.springframework.stereotype.Controller
type="assignable" 排除某个具体的类
expression="" 类的全类名
后面一般不使用
type="custom" 自定义一个 org.springframework.core.type.filter.TypeFilter
里面只有一个match方法,该方法返回true就要
type="aspectj" aspectj表达式
type="regex" 还可以使用正则表达式1 | <context:component-scan base-package="xyz.lyhcc"> |
实验18:使用@Autowired注解实现根据类型实现自动装配★
使用@Autowired注解,Spring会自动为这个属性赋值
- 首先进行告诉Spring自动扫描组件
<context:component-scan base-package=”xyz.lyhcc”>
- 使用@Autowired
- BookServlet.java
1
2
3
4
5
6
7
8
9
10@Controller
public class BookServlet {
@Autowired
private BookService bookService;
public void doGet() {
System.out.println("保存数据中...");
bookService.save();
}
} - BookDao.java
1
2
3
4
5
6
7@Repository
public class BookDao {
public void saveBook() {
System.out.println("保存图书...");
}
} - BookService.java
1
2
3
4
5
6
7
8
9
10
11@Service
public class BookService {
@Autowired
private BookDao bookDao;
public void save() {
System.out.println("BookService正在调用DAO存储数据");
bookDao.saveBook();
}
}
- BookServlet.java
说明:
- 先按照类型去找相应的组件: bookSevice = ioc.getBean(BookServlet.class)
- 找到一个就直接赋值
- 没找到,报异常
- 找到多个?装配上
- 按照变量名作为id,继续匹配,
- 匹配上?装配
- 没有匹配?报异常 (原因是按照变量名作为id进行匹配,@Qualifier可以指定id名)
- 找到装配上,没找到报异常
- 按照变量名作为id,继续匹配,
- @Autowired标注的自动装配的属性默认一定装配上的,找到就装配,找不到就不装配
- @Autowired(required=false)
实验19:如果资源类型的bean不止一个,
默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★实验20:如果根据成员变量名作为id还是找不到bean,
可以使用@Qualifier注解明确指定目标bean的id★实验21:在方法的形参位置使用@Qualifier注解
1 | //ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE |
实验22:@Autowired注解的required属性指定某个属性允许不被设置
见以上说明实验23:测试泛型依赖注入★

与@Autowired等同的还有,@Resource,@Inject
@Autowired: 最强大,离开Spring不能使用
@Resource: java标准,扩展性更强, 如果 切换在其他的容器框架 仍可以使用
@Inject : EJB