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

来源:互联网 发布:淘宝客传销 编辑:程序博客网 时间:2024/05/21 21:01

 

 

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