- 浏览: 113049 次
- 性别:
- 来自: 济南
-
文章分类
最新评论
-
tuposky:
请教楼主,怎么在line 或 Circle 里面加一个titl ...
svg DOM的一些js操作 -
tuposky:
good...真全
svg DOM的一些js操作 -
温柔企鹅:
功力太浅,表示压力很大!
ExtJS中ajax回调函数,关于scope和createDelegate() -
jie523314:
miracletree 写道 好!太感谢你了
在ModalDialog中操作父窗口对象 -
miracletree:
好!太感谢你了
在ModalDialog中操作父窗口对象
装配Bean:即依赖注入
在Spring中,对象间的协作是通过IoC机制完成的。
反向控制也叫依赖注入(Dependency Injection,DI),简单来说就是将JavaBean需要的
对象通过配置文件加载进来。
Spring提供了两种装配Bean的容器,一是BeanFactoy,另一个是ApplicationContext。
两者做为容器,所有的Bean都应该通过容器装配,而容器也知道自己都装配了哪些Bean。
Bean装配实际上就是让容器知道程序中都有哪些Bean,可以通过以下两种方式实现:
配置文件(最为常用,体现了依赖注入DI的思想)
编程方式(写的过程中向BeanFactory去注册)
ApplicationContext与BeanFactory都是接口,ApplicationContext是由BeanFactory
接口扩展而来,它增强了BeanFactory的功能。
Bean容器能够加载的对象并不一定是严格遵循JavaBeans规范的Java类,任何可实例化的类都
可以通过Spring Bean容器加载进来。通常称这些类为POJO。
要记住,BeanFactory不仅仅只具备实例化Bean的功能,它还知道所有的Bean,可以配置和管理它们。
Spring给出一些BeanFactory的实现类,其中最为常用的是XmlBeanFactory。
1、通过文件系统
Resource res = new FileSystemResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
2、通过类路径
ClassPathResource res = new ClassPathResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
3、通过ApplicationContext加载
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"} );
BeanFactory factory = (BeanFactory) appContext;
sping-frameword-1.2.7-with-dependencies中的dist里面是spring的包
将其中的spring.jar加入工程的类路径里面,下一步是写个javaBean
package bean ;
public class HelloBean
{
public HelloBean
{
System.out.println("init!");
}
private String msg ;
//加上getter和setter方法
};
public class Demo
{
public static void main(String[] args)
{
Resource res = new ClassPathResource("bean.xml") ;
//配置文件放在类路径的根路径下
BeanFactory factory = new XmlBeanFactory(res) ;
//在dist文件夹里面有spring-beans的dtd文档
HelloBean bean = (HelloBean)factory.getBean("hello") ;
//根据xml配置文件中的id号去找bean,然后从这个工厂中取出bean
System.out.println(bean.getMsg());
HelloBean bean1 = (HelloBean)factory.getBean("hello") ;
System.out.println(bean==bean1); //因为配置文件中的singleton设置为true,
//故是单例模式,所以两个bean肯定一样,所以打印true
//只有ApplicationContext才能实现bean的非延迟加载功能,所以要想让bean中的
//"init!"字符串在"before getbean!"字符串之前显示的话,那么首先必须得是单例模式,
//然后还得设置lazy-init="false",才可以做到,如果singleton="false"的话,是无法
//做到非延迟加载的!可以通过下面的代码来验证,看"before getbean!"和"init!"这两个
//字符串出现的先后顺序就一目了然了。
ApplicationContext factory = new ClassPathXmlApplicationContext("bean.xml");
System.out.println("before getbean!");
HelloBean bean2 = (HelloBean)factory.getBean("hello");
}
}
配置文件bean.xml:
将<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
拷贝进去……
<beans>
//singleton属性表明容器的bean是否使用单例模式……
//默认情况下,beanFactory就是延迟加载的
<bean id="hello" class="bean.HelloBean" singleton="true"
lazy-init="false">
<property name="msg">
<value>Hello,Spring!</value>
</property>
</bean>
</beans>
//上面的配置文件将属性的值注入到bean的属性中,这就是依赖注入的一个例子
//同时将那个javaBean注册到容器中
通常可以通过三种方式装配Bean
通过setter方法
通过构造函数
自动装配
其中,使用setter方法装配Bean是最为常用的。
如下代码的执行结果是什么?
FirstBean bean = (FirstBean)factory.getBean("my");
FirstBean bean1 = (FirstBean)factory.getBean("my");
System.out.println(bean==bean1);
结果依赖于bean元素的singleton属性,如果设置true,则以单例模式加载bean,
则永远指向同一个bean;反之则每次实例化一个。
也即在单例模式下,BeanFactory维护所有的bean
如果想让一个单例模式的bean被清理掉的话,不能简单的将bean置为null,而是必须使用
destroySingletons方法
还有一个destroyBean(String beanName,Object bean)
这两个方法都可以来垃圾回收单例模式中的bean
---------------------------------------------------------------
延迟加载:
如下代码执行的结果是什么?
System.out.println("before loading");
FirstBean bean = (FirstBean)factory.getBean("my");
System.out.println(“after loading”);
在bean的构造函数中,包含:
System.out.println(“bean init”);
结果依赖于bean的lazy-init属性,如果设置为true,则在第一次加载该bean时初始化;
否则在初始化容器时就加载所有bean。
延迟加载仅在bean单例模式下起作用。
-------------------------------------------------------------------------
初始化和清理:
Spring的初始化肯定是在依赖注入(属性设置)全部完成后才去做的。
框架提供的初始化方法肯定是先于我们自己定义的初始化方法的!比如,如果继承了
InitializingBean的话,会有一个这个接口提供的初始化方法,叫做afterPropertySet,
它的执行就是先于你定义的初始化方法的……
同理,DisposableBean接口中也定义了一个清理的方法,这个方法肯定也是先于你定义的
清理方法的!
建议使用你自己定义的初始化和清理方法,不要使用容器提供的,这样可以避免bean被污染!!!
在许多情况下,需要在对象加载后立即初始化资源,而在删除对象前先清理资源
在spring中,提供了两种方式实现初始化和清理工作。
通过设置bean的init-method和destroy-method指定初始与清理方法
通过实现InitializingBean及DisposableBean接口,由容器在加载与删除bean时自动调用。
//既然定义了一个init方法,所以可以在javaBean中设置下面的初始化方法:
public void init()
{
}
//同样销毁方法也可以类似的定义:
public void destroy()
{
}
//特别注意,如果你想运行上面自定义的destroy方法的话,你必须首先执行
factory.destroySingletons();
//否则不会去执行你上面自定义的destroy方法的!
原型bean在创建之后就脱离了factory的管理,所以呢,对于原型bean,只能初始化,而
不可以清理
<bean id="first" class="mybeans.FirstBean" init-method="init"
destroy-method="destroy" >
<property name="message">
<value>Hi,Rod Johnson</value>
</property>
</bean>
可以通过destroySingletons方法删除所有单例bean
原型bean在创建后即脱离BeanFactory的维护,所以只能调用初始化方法,而不能做清理工作。
===========================================================================
public class HelloBean implements BeanNameAware, BeanFactoryAware
{
private BeanFactory factory ;
private String name ;
public void setBeanName(String a)//由BeanNameAware继承来
{
this.name = a ;
}
//由BeanFactoryAware继承而来。
public void setBeanFactory(BeanFactory factory)
throws BeanException
{
this.factory = factory
}
}
-------------------------------------------------------
下面说说编程式加载Bean方式:
XmlBeanFactory提供两种编程方式加载Bean:
registerSingleton和registerBeanDefinition,前者不参与bean生命周期
后者参与bean的生命周期。
public static void main(String[] args)
{
Resource res = new ClassPathResource("bean.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
factory.registerSingleton("bb",new HelloBean());
HelloBean bean = (HelloBean)factory.getBean("bb");
System.out.println(bean.getMsg());
factory.destroySingletons();
}
如果使用BeanDefinition的话
public static void main(String[] args)
{
Resource res = new ClassPathResource("bean.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setBeanClass(HelloBean.class);
rbd.setInitMethodName("init");
//上面这句话告诉Spring自定义的方法名字叫做init,如果不写的话,自定义的
//初始化方法不会执行的。
/*
RootBeanDefinition rbd1 = new RootBeanDefinition(Integer.class);
ContructorArgumentValues cav = new ConstructorArgumentValues();
cav.addGenericArgumentValue("12");
rbd1.setConstructorArgumentValues(cav);
factory.registerBeanDefinition("aa",rbd1);
System.out.println(factory.getBean("aa"));
*/
factory.registerBeanDefinition("aa",rbd);
HelloBean bean = (HelloBean)factory.getBean("aa");
System.out.println(bean.getMsg());
factory.destroySingletons();
}
老师的关键代码如下:
XmlBeanFactory factory = new XmlBeanFactory(res);
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setBeanClass(HelloBean.class);
rbd.setInitMethodName("init");
RootBeanDefinition rbdi = new RootBeanDefinition(Integer.class);
ConstructorArgumentValues cav = new ConstructorArgumentValues();
cav.addGenericArgumentValue("12");
rbdi.setConstructorArgumentValues(cav);
=====================================================================
bean里面的属性是各式各样的,我们上面使用的实体类只是使用了String类型,根本没有考虑
其他的类型
bean装配方式:
通过Setter方法、通过构造函数、自动装配三种方法都可以达到装配Bean的目的。
其中使用setter方法装配Bean是最为常用的。
先说一下setter方法的装配:
setter方法可以装配基本类型、Bean类型、内部bean类型、集合类型、设置空值
所谓Bean类型属性是指这个属性类型是个javaBean,并且这个javaBean必须已经在Spring
中注册过了!
对于基本数据类型,
可以包括八种基本类型以及其包装类
<property name="" value="" />就可以了,不用在意具体类型,Spring会自动转换的。
装配基本类型:
包括八种基本类型及它们的包装类,还有String类型。
不必关心具体类型,spring可以通过反射机制了解到属性的类型信息
可以通过<property>的子元素<value>来设置基本类型的值,也可以通过其属性value来设置,
效果完全相同。
<bean id="first" class="mybeans.FirstBean" >
<property name="message">
<value>Hi, Rod Johnson</value>
</property>
<property name="age" value="1" />
//注意不能同时使用value子元素和value属性
</bean>
--------------------------------------------------------------------------
装配bean类型属性:
只有通过配置文件向容器注册的bean才能通过注入机制设置到其它bean的属性上。
使用<ref>子元素或ref属性设置
Spring即是通过这种方式建立起bean间的依赖关系,实现强大的bean管理功能。
举例说明:
BasicDataSource
引入包commons-dbcp、commons-pool以及commons-collections三个包引入
还有mysql的驱动程序
将BasicDataSource中的setter方法注入Spring中去。
在bean.xml中:
//将BasicDataSource中的setter方法中的对应值设置进去!
<beans>
<bean id="data" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///j2ee"/>
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="course" class="bean.CourseBean">
<property name="dataSource" ref="data"/>
//由于是bean,所以使用ref!
</bean>
</beans>
建立一个Bean,对应数据库中的一个表
public class CourseBean
{
private int id ;
private String name ;
private DataSource dataSource ;
//加入getter和setter方法
public void save()
{
}
}
然后就可以进行一下数据库的操作了……
在main函数中执行下面的代码:
---------------------------------------------------------------
Resource res = new ClassPathResource("bean.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
CourseBean course = (CourseBean)factory.getBean("course");
//由于数据源和courseBean之间的依赖关系已经通过配置文件给配置好了,所以这里
//只需要得到courseBean,就自然有了数据源的bean了。
course.setName("adsf");
course.save();
-----------------------------------------------------------------
所谓DAO就是既有值,又可以将这个值存入数据库的对象,也就是数据库访问对象
Data Access Object
所谓VO就是仅仅有值,也就是value object,值对象。
上面的这个course就是DAO了。
上面的save方法可以简单的写成下面的样子:
public void save()
{
try
{
Connection con = this.dataSource.getConnection();
String sql = "insert into courses (coursename,period)"+
"values(rtrim(?),rtrim(?))" ;
PreparedStatement pstmt = con.prepareStatement(sql) ;
pstmt.setString(1,this.coursename);
pstmt.setInt(2,this.period.intValue());
pstmt.executeUpdate();
}
catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
======================================================================
如果一个bean在使用前,其某个属性的值必须已经通过注入机制注入,spring可以协助检查这个属性
是否被初始化。
bean的属性dependency-check即用来实现这样的功能,其可选值包括
none --不检查
objects --仅检查bean类型
simple --仅检查基本类型(8种)和String类型
all --全检查
default --默认,不检查
此外,因为可能会调用其它对象的方法,有时一个对象在使用前必须要求另外一个对象已经初始化完成
这种依赖关系可以通过depends-on属性来实现,spring会保证在初始化当前对象前将depends-on
指定的对象也初始化出来。
如果依赖多个对象,使用逗号将它们的名字分开。
内部Bean
<bean id="outer" class="...">
<property name="target">
<bean class="com.mycompany.PersonImpl">
<property name="name">
<value>Tony</value>
</property>
</bean>
</property>
</bean>
----------------------------------------------------
Spring支持以下四种集合的装配:
<list>--java.util.List
<set>--java.util.Set
<map>--java.util.Map
<props>--java.util.Properties
list:
<property name="someList">
<list>
<value>someValue</value>
<ref bean="myDataSource"/>
<list>
<value>anyValue</value>
</list>
</list>
</property>
set:
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource"/>
</set>
</property>
map:
<property name="someMap">
<map>
<entry>
<key><value>yup an entry</value></key>
<value>just some string</value>
</entry>
<entry>
<key><value>yup a ref</value></key>
<ref bean="myDataSource"/>
</entry>
</map>
</property>
props:
<property name="people">
<props>
<prop key="HarryPotter">
The magic property
</prop>
<prop key="JerrySeinfeld">
The funny property
</prop>
</props>
</property>
==========================================================
==========================================================
如果属性没有setter方法的话,需要考虑使用构造方法装配pbean的属性,这就是
构造装配
一般在以下情况使用:
属性没有setter方法,是只读属性
属性只需要设置一次,以后就不会再更改
一般使用构造装配只装配少量属性
注意在构造装配下,构造函数中应该包含有需要装配的属性
比如:
<bean id="i" class="java.lang.Integer">
<constructor-arg value="23" />
</bean>
这就是利用构造函数将Integer注入到容器中去。
Integer i = (Integer)factory.getBean("i");
System.out.println(i);
-----------------------------------------------------
<bean id="first" class="mybeans.FirstBean">
<constructor-arg>
<value>http://www.sohu.com</value>
</constructor-arg>
<constructor-arg>
<value>http://localhost:8080</value>
</constructor-arg>
<property name="age" value="1" />
</bean>
多个参数时使用多个constructor-arg指定,出现次序决定了参数次序,或者使用index属性指定
======================================================
自动装配:
可以通过spring框架自动为bean装配属性。
自动装配只能装配bean类型,即取代ref元素。
使用自动装配只需在bean元素中加入属性autowire,自动装配可被手动装配覆盖。
也可以选择在beans中加入default-autowire属性,为所有bean设置默认自动装配。
“no“-不使用自动装配,spring推荐。
“byName”-依据名称或ID装配bean,如果没有找到,则不装配,可依赖dependency-check
属性检查是否装配。
“byType”-依据类型自动装配,如果存在两个以上同种类型,则抛出异常。
“constructor”-依据当前bean构造函数装配,查找与构造函数参数同类型bean
“autodetect”-自动检测,先通过constructor,再使用byType
Spring是不推荐使用自动装配的,首先是系统开销的问题,还有就是同名的设置可能会导致
意外的问题……
====================================================================
通过BeanFactory获取Bean与直接new一个Bean是完全不同的。
不相同的地方在于:从factory中得到的bean是被注入依赖关系的bean,而new出来的bean
则没有依赖关系,属性是空的。
通过BeanFactory获取的bean能将所有依赖注入到bean中,属性的值会依设置而定。
New出来的bean属性值必须主动设置。
在需要使用spring框架情况下,所有bean都应该由容器来管理。
===================================================================
单例和原型的问题:依赖于singleton参数,true为单例模式。
延迟加载:体现在整个容器初始化的时候立刻加载bean还是等到使用这个bean的时候才加载。
factory.getBean的时候就已经是开始使用bean了,并不一定要访问其中的属性
才算是使用。
只有ApplicationContext才能做到容器初始化的时候立刻加载bean,BeanFactory
是做不到的。
注册bean的时候,name属性是用的别名,id属性标明真名。name一般是在web开发里面去用,name
里面是可以包含一些特殊符号的,用于告诉开发者当前的属性代表什么具体的实际意思。
setter方法、构造函数和自动装配三种装配bean的方式
=====================================================================
ApplicationContext:
ApplicationContext与BeanFactory的作用相类似,都起到装配、管理Bean的作用。
不同的是,ApplicationContext在此基础上增强了BeanFactory的功能,这包括国际化、
加载资源、发布事件等等。
国际化的支持:
Spring提供了两个实现了MessageSource接口的类,它们都在
org.springframework.context.support包中:
ResourceBundleMessageSource使用JFC中标准的java.util.ResourceBundle来操作资源
ReloadableResourceBundleMessageSource 可以在不重启虚拟机的情况下重新加载资源。
ResourceBundleMessageSource是具体的类而且有setter方法,所以可以注入
根据setBasename,
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="bean.res" />
</bean>
千万注意一点,只要是资源包的话,id必须起名字为“messageSource”!!!!
这里还需要在bean包下面建立一个资源包res.properties,
在里面写上:
msg=Hello,{0}
public static void main(String[] args)
{
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("bean.xml");
String s = context.getMessage("msg",new Object[]{"Spring-Hibernate"},new Locale("zh"));
System.out.println(s);
}
这就打印出了“Hello,Spring-Hibernate”
------------------------------------------
假如有多个资源包呢?
比如我又在bean包里面建了一个ress.properties
m=M
那么
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>bean.res</value>
<value>bean.ress</value>
</list>
</property>
</bean>
--------------------------------------------------------
可以通过IOC机制加载资源,如
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>springResource</value>
</property>
</bean>
或者
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>format</value>
<value>exceptions</value>
<value>windows</value>
</list>
</property>
</bean>
千万注意一点,只要是资源包的话,id必须起名字为“messageSource”!!!!
相关推荐
Spring、SpringMVC和Mybatis是Java开发中最常用的三大开源框架,它们的整合使用,通常被称为SSM框架。这个框架组合提供了完整的后端服务解决方案,包括依赖注入(DI)、面向切面编程(AOP)、模型-视图-控制器(MVC...
弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件。本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,...
java *spring工具类 方便在非spring管理环境中获取beanjava *spring工具类 方便在非spring管理环境中获取beanjava *spring工具类 方便在非spring管理环境中获取beanjava *spring工具类 方便在非spring管理环境中获取...
Spring Integration + Spring WS 整合 在 Java 领域中,Spring Integration 和 Spring WS 是两个常用的框架,它们分别负责集成系统和 Web 服务。今天,我们将探讨如何将这两个框架整合在一起,实现一个完整的 Web ...
包含spring 3.0.5的所有jar文件: org.springframework.aop-3.0.5.RELEASE.jar org.springframework.asm-3.0.5.RELEASE.jar org.springframework.aspects-3.0.5.RELEASE.jar org.springframework.beans-3.0.5.RELEASE...
Spring Batch是一个轻量级的,完全面向Spring的批处理框架,可以应用于企业级大量的数据处理系统。Spring Batch以POJO和大家熟知的Spring框架为基础,使开发者更容易的访问和利用企业级服务。Spring Batch可以提供...