重新温习spring-bean的创建
使用spring进行web开发很长时间了,但对于spring中原理的东西一直都很模糊,只是当初在学习spring的时候看过spring的源码,但现在已经记不清了,只记得依赖注入和AOP。
spring通过应用上下文(Application context)装载bean并且把他们组装起来。应用上下文是基于BeanFactory派生出来的,包括了BeanFactory的所有功能,除非有特殊情况,一般推荐使用应用上下文。BeanFactory使用的是延迟加载,只有当应用使用到这个bean是,才会进行创建,而Application Context是在spring启动的时候进行对bean进行创建,便于发现bean的错误。
加载Application Context三种经常用到的实现:
- ClassPathXmlApplicationContext:从类路径中加载。
- FileSystemXmlApplicationContext:从文件系统加载。
- XmlWebApplicationContext:从web系统中加载。
使用应用上下文配置bean,在xml中使用bean标签进行配置,id是这个bean的id,class是这个bean的对象路径,scope是bean的作用域(singleton,prototype,request,session,global-session)说明见下图:
init-method初始化bean时调用的方法destroy-method销毁bean时调用的方法,创建和销毁的方法也可以在beans标签的default-init-method和default-destroy-method统一定义.
如果使用的是应用上下文配置的bean,在加载xml时就会调用初始化方法,在关闭Application Context时就会调用销毁方法。
在xml中配置如下:
<bean id="tom" class="com.my.study.Student" init-method="initMethod" destroy-method="destoryMethod"> <property name="id" value="10001"/> <property name="name" value="tom"/> <property name="age" value="15"/> <property name="grade" value="1"/> </bean>
统一配置方法初始化和销毁方法如下:
<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" default-init-method="initMethod1" default-destroy-method="destoryMethod1">
测试发现如果在beans和bean都配置初始化和销毁方法,spring会执行bean里配置的方法。
如果在beans标签中配置的方法在bean中没有定义,在spring启动时不会报错,如果在bean标签中配置的方法在bean中没有定义,则在spring启动时会报错。
bean标签可以注入其他bean:
<bean id="jerry" class="com.my.study.Teacher"> <property name="id" value="200001"></property> <property name="name" value="jerry"></property> </bean> <bean id="tom" class="com.my.study.Student" init-method="initMethod" destroy-method="destoryMethod"> <property name="id" value="10001"/> <property name="name" value="tom"/> <property name="age" value="15"/> <property name="grade" value="1"/> <property name="teacher" ref="jerry"></property> </bean> </beans>
bean标签里可以使用property标签对bean中的属性进行注入,不仅仅可以注入基础的数值,还可以注入list,map等其他集合,
这个是map中entry的属性字段:
注入list的方式如下:
<bean id="tom" class="com.my.study.Student" init-method="initMethod" destroy-method="destoryMethod"> <property name="id" value="10001"/> <property name="name" value="tom"/> <property name="age" value="15"/> <property name="grade" value="1"/> <property name="teacher" ref="jerry"></property> <property name="subjectList"> <list> <value>"语文"</value> <value>"数学"</value> </list> </property> </bean>
当然list下面也可以选择ref注入其他bean,set的方式和list一样。
map的注入方式如下:
<bean id="jerry" class="com.my.study.Teacher"> <property name="id" value="200001"></property> <property name="name" value="jerry"></property> </bean> <bean id="tom" class="com.my.study.Student" init-method="initMethod" destroy-method="destoryMethod"> <property name="id" value="10001"/> <property name="name" value="tom"/> <property name="age" value="15"/> <property name="grade" value="1"/> <property name="teacher" ref="jerry"></property> <property name="subjectList"> <list> <value>"语文"</value> <value>"数学"</value> </list> </property> <property name="teacherSubject"> <map> <entry key="语文" value-ref="jerry"/> </map> </property> </bean>
最后再加个知识点,SpEL表达式:
简单SpEL表达式是对字面上的值,bean的某个属性或者某个类的常量进行求值
字面值
<property name="age" value="#{15}"/>
bean的某个属性
<entry key="#{jerry.name}" value-ref="jerry"/>
bean
<entry key="语文" value="#{jerry}"/>
这里引入bean是就不需要用ref-value,如果用SpEL只需要使用value即可
SpEL表达式可以使用?.替代.来防止出现空指针异常。
如
<entry key="#{jerry.getName().toUpperCase()}" value-ref="jerry"/>
这里如果jerry.getName()为空则会出现空指针异常。可以使用?.如果前面的方法返回为NULL时,就不会执行后面的方法。
<entry key="#{jerry.getName()?.toUpperCase()}" value-ref="jerry"/>
操作类
<property name="age" value="#{T(java.lang.Math).random()}"/>
这里T()返回的是java.lang.Math的对象
SpEL操作运算
比较运算符
逻辑运算符
条件表达式
正则表达式
SpEL表达式还可以访问集合这里就不过多介绍。可以查看《spring实战第三版》第二章P58查看详细的。
上面使用到的截图是从《spring实战第三版》中截取,后面会继续完善。