您的位置:首页 > 编程语言 > Java开发

Spring 2.5 ( 传智播客) ----笔记

2011-02-11 13:55 197 查看
Spring 2.5

1)

www.springframework.org

dist/spring.jar

lib/jakarta-commons/commons-logging.jar

lib/aspectj/aspectjweaver.jar和aspectjrt.jar

lib/cglib/cglib-nodep-2.1_3.jar

lib/j2ee/common-annotations.jar

2)

在类路径下寻找配置文件

ApplicationContext ctx=new ClassPathXmlApplicationContext(new String[]{"beans.xml"});

在文件系统路径下寻找

ApplicationContext ctx=new FileSystemXmlApplicationContext(new String[]{"d://beans.xml"});

可以指定多个配置文件,通过String数组传入

3)

<bean id=“orderService" class="cn.itcast.OrderServiceBean"/>

使用静态工厂方法实例化

<bean id="personService" class="cn.itcast.service.OrderFactory" factory-method="createOrder"/>

public class OrderFactory {

public static OrderServiceBean createOrder(){

return new OrderServiceBean();

}

}

使用实例工厂方法实例化:

<bean id="personServiceFactory" class="cn.itcast.service.OrderFactory"/>

<bean id="personService" factory-bean="personServiceFactory" factory-method="createOrder"/>

public class OrderFactory {

public OrderServiceBean createOrder(){

return new OrderServiceBean();

}

}

4)Bean的作用域

singleton

prototype

<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" scope="prototype"></bean>

5)bean的生命周期

 默认在容器实例化时即实例化

 如果是prototype则是在获取的时候才实例化

  lazy-init="true"

或<beans ... default-lazy-init="true" >则所有的bean都默认在容器启动时即实例化

init-method=""

destroy-method="destroy"

AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");

ctx.close();

正常关闭时会得到调用

6)

由于spring的schema文件位于网络上,如果机器不能连接到网络,那么在编写配置信息时候就无法出现提示信息,解决方法有两种:

1。让机器上网,eclipse会自动从网络上下载schema文件并缓存在硬盘上。

2。手动添加schema文件,方法如下:

windwos->preferences->myeclipse->files and editors->xml->xmlcatalog

点"add",在出现的窗口中的Key Type中选择URI,在location中选"File system",

然后在spring解压目录的dist/resources目录中选择spring-beans-2.5.xsd,

回到设置窗口的时候不要急着关闭窗口,应把窗口中的Key Type改为Schema location,

Key改为http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7)

<bean id="personDao" class="cn.itcast.impl.PersonDaoBean" ></bean>

<bean id="orderService" class="cn.itcast.service.OrderServiceBean">

<property name="name" value="aa"/>

<property name="personDao" ref="personDao" > </property>

</bean>

8) spring注入原理模拟

(1) class ProperrtyDefiniton有三个属性

     private String name

private String ref

private String value

(2)读取applicationContext.xml时的关键代码

XPath propertysub=element.createXPath("ns:property");

propertysub.setNamespaceURIs(nsMap);

List<Element> propertys=propertysub.selectNodes(element);

for(Element property:propertys){

String propertyName=property.attributeValue("name");

String propertyref=property.attributeValue("ref");

String propertyValue=property.attributeValue("value");

PropertyDefinition propertyDefinition=new PropertyDefinition(propertyName,propertyref,propertyValue);

beanDefine.getPropertys().add(propertyDefinition);

}

(3)注入的关键代码

//beanDefinition 存放applicationContext.xml中的一个<bean>节点,这个节点下可能有多个<property>节点

//Object bean=sigletons.get(beanDefinition.getId());

//sigletons中存放整个applicationContext.xml中的<beans>节点

PropertyDescriptor[] ps=Introspector.getBeanInfo(bean.getclass()).getPropertyDescriptors();

for(PropertyDefiniton propertyDefinition:beanDefinition.getPropertys()){//循环从xml文件的bean节点获取的<property>节点

for(PropertyDescriptor properdesc:ps){  //循环从class文件中得到属性信息

if(propertyDefinition.getName().equals(properdesc.getName())){  

Method setter=properdesc.getWriteMethod();

if(setter!=null){

object value=null;

if(propertyDefinition.getRef()!=null&&!"".equals(propertyDefinition.getRef().trim())){

value=sigletons.get(propertyDefinition.getRef());

}

else{ //参见commons-beanutils-1.8.0.jar

value=ConvertUtils.convert(propertyDefinitoin.getValue().properdesc.getPropertyType());

}

setter.setAccessible(true);

setter.invoke(bean,value);

}

break;

}

}

}

(4)

apache-commons/commons-beanutils-1.8.0.jar

9)各种依赖注入方式

  <bean id="personService class="cn.itcast.service.impl.PersonServiceBean">

<property name="psesonDao">

<bean class="cn.itcast.dao.impl.PersonDaoBean"/>

</property>

<property name="name" value="itcast" /> <!-- String -->

<property name="id" value="88" /> <!-- Integer -->

<property name="lists">

<list>

<value>lihuoming</value>

</list>

</property>

<property name="sets">

<set>

<value>set</value>

</set>

</property>

<property name="maps">

<map>

<entry key="lihuoming" value="28"/>

</map>

</property>

<property name="properties">

<props>

<prop key="12">sss</prop>

</props>

</property>

</bean>

private Set<String> sets = new HashSet<String>();

private List<String> lists = new ArrayList<String>();

private Properties properties = new Properties();

private Map<String, String> maps = new HashMap<String, String>();

10)使用构造器注入

  <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">

<constructor-arg index="0" type="cn.itcast.dao.PersonDao" ref="personDao"></constructor-arg>

<constructor-arg index="1" type="java.lang.String" value="传智播客" ></constructor-arg>

11)使用@Resource注解完成属性装配

要更改 xml文件的头部信息

额外缩进的行是新增的

<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">
<context:annotation-config/>

</beans>

AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,

PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor

@Resource注解在spring安装目录的lib/j2ee/common-annotations.jar

@Autowired 默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

@Autowired

private PersonDao personDao;//用于字段上

@Autowired

public void setOrderDao(OrderDao orderDao) {//用于属性的setter方法上

this.orderDao = orderDao;

}

@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,

可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:

@Autowired @Qualifier("personDaoBean")

private PersonDao personDao;

@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。

名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,

即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,

即默认取属性名作为bean名称寻找依赖对象。

@Resource(name=“personDaoBean”)

private PersonDao personDao;//用于字段上

注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。

但一旦指定了name属性,就只能按名称装配了。

可以不加入get,set方法,非常简洁

12)注释的原理

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD,ElementType.METHOD})

public @interface ItcastResource{

public String name() default "";

}

private void annotationInject(){

for(String beanName:sigletons.keySet()){

Object bean=sigletons.get(beanName);

if(bean!=null){

try{

PropertyDescriptor[] ps=Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();

for(PropertyDescriptor properdesc:ps){

Method setter=properdesc.getWriteMethod();

if(setter!=null&&setter.isAnnotationPresent(ItcastResource.class)){

ItcastResource resource=setter.getAnnotation(ItcastResource.class);

Object value=null;

if(resource.name()!=null&&!"".equals(resource.name())){

value=sigletons.get(resource.name());

}

else{

value=sigletons.get(properdesc.getName());//这行有点问题,实参应该是setter的形参的变量名,

//或许应该是setter.getTypeParameters()

if(value==null){

for(String key:sigletons.keySet()){

if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){

value=sigletons.get(key);

break;

}

}

}

}

setter.setAccessible(true);

setter.invoke(bean,value);

}

}

Field[] fields=bean.getClass().getDeclaredFields();

for(Field field:fields){

if(field.isAnnotationPresent(ItcastResource.class)){

ItcastResource resource=field.getAnnotation(ItcastResource.class);

Object value=null;

if(resource.name()!=null&&!"".equals(resource.name())){

value=sigletons.get(resource.name());

}

else{

value=sigletons.get(field.getName());

if(value==null){

for(String key:sigletons.keySet()){

if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){

value=sigletons.get(key);

break;

}

}

}

}

field.setAccessible(true);

field.set(bean,value);

}

}

}catch(IntrospectionException e){

e.printStackTrace();

}

}

}

}

13)让Spring自动扫描和管理Bean

前面的例子我们都是使用XML的bean定义来配置组件。在一个稍大的项目中,

通常会有上百个组件,如果这些这组件采用xml的bean定义来配置,显然会增加配置文件的体积,

查找及维护起来也不太方便。spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注了

@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。

它的作用和在xml文件中使用bean节点配置组件是一样的。要使用自动扫描机制,我们需要打开以下配置信息

通过在classpath自动扫描方式把组件纳入spring 容器中管理

<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">
<context:component-scan base-package="cn.itcast"/>

</beans>

其中base-package为需要扫描的包(含子包)。

@Service用于标注业务层组件、 @Controller用于标注控制层组件(如struts中的action)、

@Repository用于标注数据访问组件,即DAO组件。而@Component泛指组件,

当组件不好归类的时候,我们可以使用这个注解进行标注。

来自于org.springframework.stereotype.Repository等

bean的名称是类的简单名称并且把首字母小写

或者

在类的定义前加上

@Service("personService")

@Scope("prototype") //org.springframework.context.annotation.Scope

@PostConstruct

<context:component-scan base-package="cn.itcast"/>这一行包括了很多处理器

其中有 <context:annotation-config/>

@PreDestroy
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: