1. 概要
struts2:web
hibernate:持久化
spring:业务层.管理bean的,容器.List Map Set. 体验spring:
1.创建java项目.
2.引入spring的类库.
${spring解压目录}/dist/spring.jar
${spring解压目录}/lib/jakarta-commons/commons-logging.jar
2'.创建业务类.
/**
* GreetingService
*/
public class GreetingService {
private String greeting ;//get/set
private String greeting2 ;//get/set /* byeService */
private ByeService bs ;//get/set
public void sayGreeting(){
bs.sayBye();
}
} /**
* ByeService
*/
public class ByeService {
private String bye ; public String getBye() {
return bye;
} public void setBye(String bye) {
this.bye = bye;
} public void sayBye(){
System.out.println(bye);
}
}
3.配置spring的配置文件.src/applicationContext.xml
schema:${spring解压目录}\docs\reference\html_single\index.html\3.2.1.1
<?xml version="1.0"?>
<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-2.5.xsd">
<!-- 欢迎服务 -->
<bean id="greetingService" class="cn.itcast.spring.service.GreetingService">
<property name="greeting">
<value>hello world</value>
</property>
<property name="greeting2" value="tom" />
<property name="bs" ref="byeService" />
</bean>
<!-- 欢送服务 -->
<bean id="byeService" class="cn.itcast.spring.service.ByeService">
<property name="bye">
<value>later</value>
</property>
</bean>
</beans>
4.创建app.
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
GreetingService gs = (GreetingService) ac.getBean("greetingService");
gs.sayGreeting();
gs.sayGreeting2(); ByeService bs = (ByeService) ac.getBean("byeService");
bs.sayBye(); spring:
ioc: inverse of control,反转控制.获得依赖对象的方式被反转了. (不要手动new bean对象)
1.new.(spring负责对象实例化)
2.组装对象的出发点是反的(相对于bean的依赖关系是反的).
DI:dependency injection,依赖注入. <==> ioc
aop: aspect oriented program,面向方面编程. oop:面向对象编程. soa: GreetingService gs = new ...(); gs.setByeService(bs); ByeService bs = new ...();
gs.sayGreeting(); BeanFactory:实例化bf时,不会实例化任何bean,只有getBean的时候,才实例化相关的bean.节省资源.
ApplicationContext:实例化ac时,实例化单例bean.
懒汉式:
public class A{
private A(){} public static A instance = null ;
public static A getInstance(){
if(instance == null){
instance = new A();
}
return instance ;
}
} 饿汉式:
public static A instance = new A(); spring单利bean,对应的bean的叫做prototype(原型bean). ac.getBean("bs"); == new ByeService(); 生命周期:
1.new
2.set DI
3.BeanNameAware:bean名关注
4.BeanFactoryAware:bean工厂关注
5.BeanPostProcessor.beforeInitialization();
5'.调用InitializingBean.afterPropertySet()方法.
6.init-method
7.BeanPostProcessor.afterInitialization(); spring()框架. 代码的入侵.
1.高侵入性
2.低侵入
3.非侵入行 jee:jsp servlet jpa jta ejb(enterprise javabean),jndi
pojo:plain old java object. BeanDefinition:bean的定义,spring对bean的信息的封装.
Root bean: class [cn.itcast.spring.service.GreetingService]; scope=singleton; abstract=false; lazyInit=false;
autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null;
factoryMethodName=null; initMethodName=ini; destroyMethodName=release; defined in class path resource
[applicationContext.xml] Class clazz = Class.forName("cn.itcast.spring.service.GreetingService");
clazz.newInstance(); scope:prototype singleton request session global_session <struts>
<package namepace extends=""> 在ide下注册spring中的schema文件.
${spring解压目录}\dist\resources\*.xsd. List Set Map:
Properies:
.properties <hibernate-mapping>
<class name table lazy>
<id >
<generator class="" />
</id>
<property name="age" column access="field">
</class> spring通过构造函数参数注入依赖强化依赖关系. 自动装配:
1.byName:按照名称自动装配,寻找和bean的属性名相一致的bean的id.(bean必须有空的构造,通过set方法注入)
2.byType:按照属性的类型来自动装配,如果找到多个,抛异常.(bean必须有空的构造,通过set方法注入)
3.constructor:按照构造函数参数的类型自动装配,如果找不到或者找多个,都抛异常.
4.autodetact:自动检测,在(2)和(3)之间选择一个 5.no.
6.default,跟<beans default-autowire属性>保持一致. 分散配置:
把需要在上下文硬编码的属性拿到外部的属性文件中定义,让上下文从外部文件提取值. 自定义编辑器:
将字符串转换成相应的对象,
2. Spring中bean的生命周期, 及其工作流程
bean被载入到容器中时,他的生命周期就开始了。bean工厂在一个bean可以使用前完成很多工作:
1).容器寻找bean的定义信息并实例化。
2).使用依赖注入,spring按bean定义信息配置bean的所有属性。
3).若bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递bean的ID。
4).若bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5).若BeanPostProcessor和bean关联,则它们的postProcessBeforeInitialization()方法被调用。
6).若bean指定了ini-method方法、,它将被调用。
7).最后,若有BeanPostProcessor和bean关联,则它们的postProcessAfterInitialization()方法被调用、。
示例代码一: BeanPostProcessor 注册bean后处理器,能给所有bean做初始和收尾工作,等效于在xml文件中配置init-method="ini" destroy-method="release"。
如果bean构造时 需要调用有参的构造函数,可以在constructor-arg 中配置。
ByeService.java , javabean
public class ByeService {
private String bye ;
public String getBye() {
return bye;
}
public void setBye(String bye) {
this.bye = bye;
}
public void sayBye(){
System.out.println(bye);
}
}
GreetingService.java, javabean
public class GreetingService implements BeanNameAware,BeanFactoryAware{
private String greeting ;
private String greeting2 ; /* byeService */
private ByeService bs ; public GreetingService(ByeService bs){
this.bs = bs ;
System.out.println("Constructor: new GreetingService()");
}
public GreetingService(String str1,String str2){
System.out.println("1111");
}
public GreetingService(String str1,Integer str2){
System.out.println("2222");
}
public GreetingService(String str1,int str2){
System.out.println("3333");
}
public GreetingService(int str1,String str2){
System.out.println("4444");
} /**
* beannameAware,注入bean的id
*/
public void setBeanName(String name) {
System.out.println("BeanNameAware:setBeanName() : " + name);
} /**
* bean工厂关注
*/
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware:setBeanFactory() : " + beanFactory);
} public ByeService getBs() {
return bs;
} public void setBs(ByeService bs) {
this.bs = bs;
System.out.println("DI:setBs() : " + bs);
} public String getGreeting() {
return greeting;
} public void setGreeting(String greeting) {
this.greeting = greeting;
System.out.println("DI:setGreeting() : " + greeting);
} public void sayGreeting(){
bs.sayBye();
}
public void sayGreeting2(){
System.out.println(greeting2);
} public String getGreeting2() {
return greeting2;
} public void setGreeting2(String greeting2) {
this.greeting2 = greeting2;
System.out.println("DI:setGreeting2() : " + greeting2);
} /**
* 定制初始化方法
*/
public void ini(){
System.out.println("ini");
} /**
* 定制销毁方法
*/
public void release(){
System.out.println("release");
}
}
MyBeanPostProcessor.java, bean的后处理器
public class MyBeanPostProcessor implements BeanPostProcessor { /**
* 后处理
*/
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("BeanPostProcessor:after:" + beanName);
return bean;
} /**
* 之前处理
*/
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("BeanPostProcessor:before:"+beanName);
return bean;
}
}
applicationContext.xml 配置文件
<?xml version="1.0"?>
<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-2.5.xsd">
<!-- 欢迎服务 -->
<bean id="greetingService" class="cn.itcast.spring.service.GreetingService"
scope="singleton"
init-method="ini"
destroy-method="release">
<constructor-arg index="1" type="java.lang.String" value="12" />
<constructor-arg index="0" type="int" value="24" />
<property name="greeting">
<value>hello world</value>
</property>
<property name="greeting2" value="tom" />
<property name="bs" ref="byeService" />
</bean>
<!-- 欢送服务 -->
<bean id="byeService" class="cn.itcast.spring.service.ByeService">
<property name="bye">
<value>later</value>
</property>
</bean> <!-- 注册bean后处理器 -->
<bean id="myBeanPostProcessor" class="cn.itcast.spring.beanprocessor.MyBeanPostProcessor" />
</beans>
App.java
public class App {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");//src下 不需要加全路径
GreetingService gs = (GreetingService) ac.getBean("greetingService");
gs.sayGreeting();
gs.sayGreeting2();
ByeService bs = (ByeService) ac.getBean("byeService");
bs.sayBye();
((ClassPathXmlApplicationContext)ac).destroy();
}
}
3. 集合装配bean
单例和原型模式:
prototype、singleton、request session、global-session ,spring中的bean缺省情况下是单例模式。始终返回一个实例。若想返回不同的实例的话需要定义成原型模式。bean的singleton属性告诉上下文该bean是否为单例的。缺省为true。若为false的话,为原型bean。
<bean id="foo" class="...Foo" singleton="false"/>
<!– spring2.5 -->
<bean scope="prototype|single|..">
<bean id="foo" class="...Foo" autowire="autowire type">
有四种自动装配类型:
1.byName:寻找和属性名相同的bean,若找不到,则装不上。
2.byType:寻找和属性类型相同的bean,找不到,装不上,找到多个抛异常。
3.constructor:查找和bean的构造参数一致的一个或多个bean,若找不到或找到多个,抛异常。按照参数的类型装配
4.autodetect:(3)和(2)之间选一个方式。不确定性的处理与(3)和(2)一致。(选择标准:是否有含参的构造函数,没有则是byType)
<bean id="bar" class="Bar" autowire="byName"/>
<!-- spring2.5 -->
@Autowired
<bean class="...
AutowiredAnnotationBeanPostProcessor">
示例代码二: (通过util定义集合bean需要手动添加 spring-util-2.5.xsd)
PopSet.java, javabean
public class PopSet {
private String[] ss ;
private List list ;
private Set set ;
private Map map ;
private Properties prop ;
.....省略 get set方法
}
popSet.xml 配置文件, java bean中的 prop 对应到配置文件中用标签<prop> </prop>配置。
<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
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-2.5.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd ">
<bean id="popSet" class="cn.itcast.spring.popset.PopSet">
<property name="ss">
<list>
<value>1</value>
<value>tom</value>
</list>
</property>
<property name="list" ref="myList" />
<property name="set">
<set>
<value>1</value>
<value>tom</value>
<ref bean="byeService"/>
<ref bean="byeService"/>
<bean class="cn.itcast.spring.service.ByeService">
<property name="bye" value="kk" />
</bean>
<bean class="cn.itcast.spring.service.ByeService">
<property name="bye" value="kk" />
</bean>
</set>
</property>
<property name="map">
<map>
<entry key="key001" value="tom" />
<entry key="key002" value-ref="byeService" />
<entry key="key003">
<bean class="cn.itcast.spring.service.ByeService" />
</entry>
</map>
</property>
<property name="prop">
<props>
<prop key="key001">tom</prop>
<prop key="key002">tom1</prop>
<prop key="key003">tom2</prop>
</props>
</property>
</bean> <bean id="byeService" class="cn.itcast.spring.service.ByeService">
<property name="bye" value="over" />
</bean> <!-- 通过util定义集合bean -->
<util:list id="myList">
<value>1</value>
<value>2</value>
<value>tom</value>
<ref bean="byeService"/>
<ref bean="byeService"/>
<bean class="cn.itcast.spring.service.ByeService">
<property name="bye" value="kk" />
</bean>
<bean class="cn.itcast.spring.service.ByeService">
<property name="bye" value="kk" />
</bean>
</util:list>
</beans>
App.java
public class App {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"cn/itcast/spring/popset/popSet.xml");
ac.getBean("popSet");
}
}
4.分散装配
将配置文件分成几个分散的配置文件。如配置数据库的 jdbc.properties文件。使用占位符变量代替bean装配文件中的硬编码配置。占位符采${variable}形式。
定制属性编辑器 , 如下利用自定义的编辑器能将 省市县装配到homeAddress对应的属性中去。
<property name="homeAddress">
<value>湖南省.长沙市.宁乡县.花明楼镇</value>
</property>
示例代码三:
Address.java, javabean
public class Address {
private String province;
private String city;
private String street;
private String zipCode;
......省略 set get方法
}
Scatter.java, javabean
public class Scatter {
private String driverClass ;
private String url ;
private String username ;
private String password ; private Address comAddress ;//公司地址
private Address homeAddress ;//家庭地址 }
jdbc.properties 分散配置的 prop文件
jdbc.driverclass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
AddressEditor.java 自定义编辑器
public class AddressEditor extends PropertyEditorSupport { public void setAsText(String text) throws IllegalArgumentException {
if(text != null && text.length() > 0){
String[] ss = text.split("\\.");
if(ss != null && ss.length > 3){
Address a = new Address();
a.setProvince(ss[0]);
a.setCity(ss[1]);
a.setStreet(ss[2]);
a.setZipCode(ss[3]);
//将转换成的地址对象设置给相应的属性上
setValue(a);
}
else{
setValue(null);
}
}
else{
setValue(null);
}
}
}
scatter.xml 配置文件
<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd ">
<!-- 分散配置(属性占位符配置器)
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:cn/itcast/spring/scatter/jdbc.properties</value>
</list>
</property>
</bean>
--> <!-- 自定义编辑器配置器 -->
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<!-- 自定义编辑器集 -->
<property name="customEditors">
<map>
<entry key="cn.itcast.spring.scatter.Address">
<bean class="cn.itcast.spring.editor.AddressEditor" />
</entry>
</map>
</property>
</bean> <bean id="scatter" class="cn.itcast.spring.scatter.Scatter">
<property name="driverClass" value="${jdbc.driverclass}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- -->
<property name="comAddress">
<bean class="cn.itcast.spring.scatter.Address">
<property name="province" value="jilin" />
<property name="city" value="cc" />
<property name="street" value="${jdbc.url}" />
</bean>
</property>
<property name="homeAddress">
<value>${jdbc.driverclass}.cc.renmin.139988</value>
</property>
</bean> <!-- 分散配置,加载分散配置的文件 -->
<context:property-placeholder location="classpath:cn/itcast/spring/scatter/jdbc.properties"/>
</beans>
App.java
public class App {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"cn/itcast/spring/scatter/scatter.xml");
ac.getBean("scatter");
}
}