1.我对spring的理解
(创建bean的三种方式:1、XML文件方式;2、Configure类方式;3、注解annotation方式。这里讨论XML方式,及其内部原理)
spring的本质就是通过XML配置来执行java代码,如新建对象(bean)、设置对象的依赖关系、调用对象的方法、生命周期的管理等。
a.调用构造器创建对象,用<bean.../>元素;
b.调用setter方法完成依赖注入,用<property.../>元素;
c.调用getter方法获取属性值,用PropertyPathFactoryBean工厂bean;
d.调用普通方法来进行运算,用MethodInvokingFactoryBean工厂bean;
e.直接获取属性值,用FieldRetrievingFactoryBean工厂bean;
2.bean的生成方式
a.调用类的构造器来创建bean:
<bean id="database" class="dao.Database" />
b.通过工厂方法创建bean:
(1)通过静态工厂方法创建bean;
<!-- spring通过静态工厂类的静态方法来创建bean,需指定静态方法 -->
<bean id="staticUser" class="factory.StaticFactory" factory-method="getBeing">
<!-- 指定静态工厂方法的参数 -->
<constructor-arg name="arg" value="user" />
</bean>
定义工厂类和静态工厂方法,spring通过调用静态工厂类的静态方法来创建bean。
(2)通过实例工厂方法创建bean:
<!-- 配置实例工厂类的bean对象,spring通过调用bean对象的工厂方法来创建其它bean -->
<bean id="instanceFactoryClass" class="factory.InstanceFactory" />
<bean id="instanceUser" factory-bean="instanceFactoryClass" factory-method="getBeing">
<!-- 指定实例工厂方法的参数 -->
<constructor-arg name="arg" value="user" />
</bean>
定义工厂类和实例工厂方法,spring通过调用工厂bean对象的工厂方法来创建新的bean。
c.通过各种FactoryBean(工厂bean)来创建bean:
(1)PropertyPathFactoryBean,用来获取目标bean的属性值(实际是其getter方法的返回值);
<!-- 通过“属性获取工厂Bean”获取目标bean的property,PropertyPathFactoryBean返回值(基本数值类型or对象)在最外层,则把返回值注册为容器中一个bean,bean名字为id -->
<bean id="vipPropertyBean" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="vipUser"></property>
<property name="propertyPath" value="user.username"></property>
</bean>
因为返回值的bean在<beans>目录下,则注册为容器中的bean。
<!-- 简写形式,直接通过指定"已存在的bean的id.property1.property2"(相当于targetBeanName.propertyPath)来获取bean的属性值,因为返回值在最外层,则注册为容器中的bean,bean名字为"已存在的bean的id.property1.property2" -->
<bean id="vipUser.user.username" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
简写形式,注册为容器中的bean。
<!-- 将返回值注册为inner bean,并将其作为依赖值注入到其它bean中。但是容器无法通过id获取到inner bean -->
<bean id="propertyBeanToUserBean" class="bean.User">
<property name="username">
<bean id="vipUser.user.username" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
</property>
<property name="password">
<bean id="vipUser.user.password" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
</property>
</bean>
因为返回的是inner bean,则作为依赖被注入,spring容器无法获取此bean。
(2)FieldRetrievingFactoryBean,用来获取类的静态属性值、或者对象的实例属性值(几乎没用,因为对象的属性值为private,应该通过getter方法获取):
<bean id="java.sql.Connection.TRANSACTION.SERIALIZABLE" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
简写方法,获取类的静态属性值,因为在<beans.../>目录下,则注册为容器中的bean。
(3)MethodInvokingFactoryBean,用来调用类的静态方法、或者调用bean对象的实例方法。若有返回值则可注册为容器中的bean或者作为依赖注入其它bean中:
<bean id="methodInvokedBean" class="bean.TestMethodInvokingFactoryBean"/>
<bean id="getMethodBean2" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name ="targetObject" ref="methodInvokedBean"></property>
<property name="targetMethod" value="func2"></property>
<property name="arguments">
<list>
.....
</list>
</property>
</bean>
调用bean的实例方法,可输入方法参数;因为在<beans.../>目录下,则生成容器中的bean,又因为此处没有返回值,则可不用指明bean id。
<bean id="getMethodBean1" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name = "targetClass" value="bean.TestMethodInvokingFactoryBean"/>
<property name="targetMethod" value="func1"/>
</bean>
调用类的静态方法,同样可选择是否输入参数or根据位置判断是否注册为容器中的bean。
(4)自定义工厂bean,需要实现FactoryBean接口:
/*
* factorybean(工厂bean),用来创建其它的bean对象
*/
public class BeingFactoryBean implements FactoryBean<Object>{
public String targetBean;
public void setTargetBean(String targetBean) {
this.targetBean = targetBean;
}
//工厂bean的此方法用来生产bean
@Override
public Object getObject() throws Exception {
// TODO Auto-generated method stub
if(targetBean.equalsIgnoreCase("user"))
return new User();
else
return new Animal();
}
@Override
public Class getObjectType() {
// TODO Auto-generated method stub
return Object.class;
}
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return false;
}
}
<!-- 配置工厂bean,返回其生产的bean -->
<bean id="factoryBeanProduct" class="bean.BeingFactoryBean">
<property name="targetBean" value="user" />
</bean>
自定义FactoryBean,通过<property.../>来驱动setter方法来设置参数,此参数会影响getObject()方法生成bean的结果。
3.依赖注入
a.通过构造器完成依赖注入:
<!-- spring容器通过构造器构造bean,并完成属性值注入 -->
<bean id="constructorBean" class="bean.ConstructorBean">
<constructor-arg name="user" ref="zp" index="0" />
<constructor-arg name="isMan" value="yes" index="1" />
</bean>
通过构造器完成依赖注入,即在新建对象时就注入参数值。
b.通过setter方法完成依赖注入:
<bean id="dbservice" class="service.DbService" scope="singleton">
<!-- 通过setter方法完成属性的依赖注入 -->
<property name="database" ref="database" />
<!-- 通过setter方法完成属性的值注入 -->
<property name="name" value="基本类型的属性值"/>
</bean>
通过<property.../>触发setter方法来完成依赖注入。
c.注入的类型:
<property name="name" value="zp"/>
<property name="name" >
<value>
zp
</value>
</property>
<property name="user" ref="zpp"/>
<property name="user">
<ref bean = "zpp">
</property>
(3)注入集合类型的值
<!-- Bean的属性是集合 -->
<bean id="collectionBean" class="bean.CollectionBean">
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value1"></entry>
<entry key="key2" value="value2"></entry>
<entry key="key3" value="value3"></entry>
</map>
</property>
<property name="array">
<list>
<value>array1</value>
<value>array2</value>
<value>array3</value>
</list>
</property>
</bean>
d.高级依赖关系:
5.生命周期和作用域
作用域:
生命周期:
<bean id="user" class="bean.User" init-method="init" destroy-method="close" scope="singleton" />
init-methon:创建Bean实例,其全部属性设置完成后执行的方法;
6.事件机制
(1)容器事件监听器:实现ApplicationListener接口的类
<!-- 配置容器事件监听器 -->
<bean class="listener.Listener" scope="prototype" />
(2)具有意识的bean
<!-- spring容器创建该bean后自动调用其方法,把容器对象自身作为参数 -->
<bean id="awareBean" class="bean.ApplicationContextAwareBean" />