(6) 用@Resource注解完成属性装配 【依赖注入----手动装配】 以及 编码解析其原理【经典】

手工装配依赖对象,在这种方式中又有两种编程方式

1. 在xml配置文件中,通过在bean节点下配置,如
   <bean id="orderService" class="cn.itcast.service.OrderServiceBean">
          <constructor-arg index=“0” type=“java.lang.String” value=“xxx”/>//构造器注入
           <property name=“name” value=“zhao/>//属性setter方法注入
    </bean>
2. 在java代码中使用@Autowired或@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



       在java代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:@Autowired 默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

(1)

    @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;


(2)

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

      名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。

    @Resource(name=“personDaoBean”)
    private PersonDao  personDao;//用于字段上


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



参照代码验证:实践出真知


  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:context="http://www.springframework.org/schema/context" 
  5.         
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  7.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
  8.            http://www.springframework.org/schema/context 
  9.            http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 
  10.            <context:annotation-config/> 
  11.             
  12.             
  13.            <bean id="personDao" class="cn.itm.dao.impl.PersonDaoBean"></bean> 
  14.            <bean id="personService" class="cn.itm.service.impl.PersonServiceBean"> 
  15.             
  16.                  <!--  
  17.                        <constructor-arg index="0" type="cn.itm.dao.PersonDao"/> 
  18.                        <constructor-arg index="1" value="大家好。"></constructor-arg> 
  19.                  --> 
  20.            </bean> 
  21.     
  22. </beans> 


2,PersonServiceBean.java


  1. package cn.itm.service.impl; 
  2.  
  3. import javax.annotation.Resource; 
  4.  
  5. import cn.itm.dao.PersonDao; 
  6. import cn.itm.service.PersonService; 
  7.  
  8. public class PersonServiceBean implements PersonService{ 
  9.  
  10.     // 首先获取,personDao的名称,然后 在SPring容器里面,寻找与此名称所匹配的bean,如果找到 就把 这个bean 注入到这个字段上来。 
  11.     @Resource private PersonDao personDao; 
  12.     private String name; 
  13.      
  14.     public PersonServiceBean(){} 
  15.      
  16.     public PersonServiceBean(PersonDao personDao, String name) { 
  17.         this.personDao = personDao; 
  18.         this.name = name; 
  19.     } 
  20.  
  21.      
  22.     public void save(){ 
  23.         personDao.add(); 
  24.     } 
  25.      


  1. package cn.itm.dao.impl; 
  2.  
  3. import cn.itm.dao.PersonDao; 
  4.  
  5.  
  6. public class PersonDaoBean implements PersonDao { 
  7.  
  8.      
  9.     public void add(){ 
  10.         System.out.println("执行PersonDaoBean的add方法。。。"); 
  11.     } 

  1. package cn.itm.dao; 
  2.  
  3. public interface PersonDao { 
  4.  
  5.     public abstract void add(); 
  6.  

  1. package cn.itm.service; 
  2.  
  3.  
  4. public interface PersonService { 
  5.  
  6.     public void save(); 

  1. package junit.test; 
  2.  
  3.  
  4. import org.junit.BeforeClass; 
  5. import org.junit.Test; 
  6. import org.springframework.context.ApplicationContext; 
  7. import org.springframework.context.support.ClassPathXmlApplicationContext; 
  8.  
  9. import cn.itm.service.PersonService; 
  10.  
  11. public class SpringTest { 
  12.  
  13.     @BeforeClass 
  14.     public static void setUpBeforeClass() throws Exception { 
  15.     } 
  16.  
  17.     // 专门用来实例化  Spring 容器的。 
  18.     @Test public void instanceSpring(){ 
  19.          
  20.         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 
  21.         PersonService personService = (PersonService) ctx.getBean("personService"); 
  22.         personService.save(); 
  23.     } 

可以正常运行,通过。


编码解析其原理:

1,主要实现的方法:

  1. /**
  2.      * 实现注解的方式  注入:
  3.      *
  4.      */ 
  5.     private void annotationInject() { 
  6.         // 循环所有的 bean对象: 
  7.         for(String beanName  : sigletons.keySet()){ 
  8.             // 获取bean对象: 
  9.             Object bean = sigletons.get(beanName); 
  10.             // 判断 bean对象是否存在: 
  11.             if(bean != null){ 
  12.                 // 得到 bean的属性描述: 
  13.                 try
  14.                     PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 
  15.                     for(PropertyDescriptor propertyDesc /*这里是 bean 里面的属性*/ : ps){ 
  16.                         // 获取setter方法: 
  17.                         Method setter = propertyDesc.getWriteMethod(); 
  18.                         if(setter != null  && setter.isAnnotationPresent(ItmResource.class)){  // 还要   看看   setter方法是否存在 注解: 
  19.                             // 取得注解: 
  20.                             ItmResource resource = setter.getAnnotation(ItmResource.class); 
  21.                              
  22.                             Object value  = null
  23.                             if(resource.name() != null && !"".equals(resource.name())){ 
  24.                                 // 判断是否在  集合里面:从集合里取出来  注入进去。 
  25.                                 value = sigletons.get(resource.name()); 
  26.                             }else
  27.                                 // 如果 没有指定 name属性  怎么办 ? 
  28.                                 value = sigletons.get(propertyDesc.getName()); 
  29.                                 if(value == null){ 
  30.                                     for(String key  : sigletons.keySet()){ // 历遍所有的bean 
  31.                                         // 是否存在  类型匹配的bean。 
  32.                                         if(propertyDesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){ 
  33.                                             value = sigletons.get(key); 
  34.                                             break
  35.                                         } 
  36.                                     } 
  37.                                 } 
  38.                             } 
  39.                             setter.setAccessible(true); 
  40.                             setter.invoke(bean, value);  // 注入进去。 
  41.                         } 
  42.                     } 
  43.                     // 对字段进行处理: 
  44.                     Field[] fields  = bean.getClass().getDeclaredFields(); 
  45.                     for(Field field : fields ){ 
  46.                         if(field.isAnnotationPresent(ItmResource.class)){ 
  47.                             // 取得注解: 
  48.                             ItmResource resource = field.getAnnotation(ItmResource.class); 
  49.                              
  50.                             Object value  = null
  51.                             if(resource.name() != null && !"".equals(resource.name())){ 
  52.                                 // 判断是否在  集合里面:从集合里取出来  注入进去。 
  53.                                 value = sigletons.get(resource.name()); 
  54.                             }else
  55.                                 // 如果 没有指定 name属性  怎么办 ? 
  56.                                 value = sigletons.get(field.getName());  // 有 name直接取得对象。 
  57.                                 if(value == null){  
  58.                                     for(String key  : sigletons.keySet()){ // 历遍所有的bean 
  59.                                         // 是否存在  类型匹配的bean。 【再根据 字段的类型去寻找】 
  60.                                         if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){ 
  61.                                             value = sigletons.get(key); 
  62.                                             break
  63.                                         } 
  64.                                     } 
  65.                                 } 
  66.                             } 
  67.                              
  68.                             field.setAccessible(true); 
  69.                             field.set(bean, value); 
  70.                         } 
  71.                     } 
  72.                 } catch (Exception e) { 
  73.                     e.printStackTrace(); 
  74.                 } 
  75.             } 
  76.         } 
  77.          
  78.     } 

2,把上面的方法放到此类中:

  1. package junit.test; 
  2.  
  3.  
  4. import java.beans.Introspector; 
  5. import java.beans.PropertyDescriptor; 
  6. import java.lang.reflect.Field; 
  7. import java.lang.reflect.Method; 
  8. import java.net.URL; 
  9. import java.util.ArrayList; 
  10. import java.util.HashMap; 
  11. import java.util.List; 
  12. import java.util.Map; 
  13.  
  14. import org.apache.commons.beanutils.ConvertUtils; 
  15. import org.dom4j.Document; 
  16. import org.dom4j.Element; 
  17. import org.dom4j.XPath; 
  18. import org.dom4j.io.SAXReader; 
  19.  
  20. public class ItmClassPathXMLApplicationContext { 
  21.      
  22.     private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>(); 
  23.     // 存放实例 
  24.     private Map<String,Object> sigletons = new HashMap<String,Object>(); 
  25.      
  26.     public ItmClassPathXMLApplicationContext(String fileName){ 
  27.         this.readXML(fileName); 
  28.         this.instanceBeans(); 
  29.         this.annotationInject(); 
  30.         this.injectObject(); 
  31.     } 
  32.  
  33.     /**
  34.      * 实现注解的方式  注入:
  35.      *
  36.      */ 
  37.     private void annotationInject() { 
  38.         // 循环所有的 bean对象: 
  39.         for(String beanName  : sigletons.keySet()){ 
  40.             // 获取bean对象: 
  41.             Object bean = sigletons.get(beanName); 
  42.             // 判断 bean对象是否存在: 
  43.             if(bean != null){ 
  44.                 // 得到 bean的属性描述: 
  45.                 try
  46.                     PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 
  47.                     for(PropertyDescriptor propertyDesc /*这里是 bean 里面的属性*/ : ps){ 
  48.                         // 获取setter方法: 
  49.                         Method setter = propertyDesc.getWriteMethod(); 
  50.                         if(setter != null  && setter.isAnnotationPresent(ItmResource.class)){  // 还要   看看   setter方法是否存在 注解: 
  51.                             // 取得注解: 
  52.                             ItmResource resource = setter.getAnnotation(ItmResource.class); 
  53.                              
  54.                             Object value  = null
  55.                             if(resource.name() != null && !"".equals(resource.name())){ 
  56.                                 // 判断是否在  集合里面:从集合里取出来  注入进去。 
  57.                                 value = sigletons.get(resource.name()); 
  58.                             }else
  59.                                 // 如果 没有指定 name属性  怎么办 ? 
  60.                                 value = sigletons.get(propertyDesc.getName()); 
  61.                                 if(value == null){ 
  62.                                     for(String key  : sigletons.keySet()){ // 历遍所有的bean 
  63.                                         // 是否存在  类型匹配的bean。 
  64.                                         if(propertyDesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){ 
  65.                                             value = sigletons.get(key); 
  66.                                             break
  67.                                         } 
  68.                                     } 
  69.                                 } 
  70.                             } 
  71.                             setter.setAccessible(true); 
  72.                             setter.invoke(bean, value);  // 注入进去。 
  73.                         } 
  74.                     } 
  75.                     // 对字段进行处理: 
  76.                     Field[] fields  = bean.getClass().getDeclaredFields(); 
  77.                     for(Field field : fields ){ 
  78.                         if(field.isAnnotationPresent(ItmResource.class)){ 
  79.                             // 取得注解: 
  80.                             ItmResource resource = field.getAnnotation(ItmResource.class); 
  81.                              
  82.                             Object value  = null
  83.                             if(resource.name() != null && !"".equals(resource.name())){ 
  84.                                 // 判断是否在  集合里面:从集合里取出来  注入进去。 
  85.                                 value = sigletons.get(resource.name()); 
  86.                             }else
  87.                                 // 如果 没有指定 name属性  怎么办 ? 
  88.                                 value = sigletons.get(field.getName());  // 有 name直接取得对象。 
  89.                                 if(value == null){  
  90.                                     for(String key  : sigletons.keySet()){ // 历遍所有的bean 
  91.                                         // 是否存在  类型匹配的bean。 【再根据 字段的类型去寻找】 
  92.                                         if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){ 
  93.                                             value = sigletons.get(key); 
  94.                                             break
  95.                                         } 
  96.                                     } 
  97.                                 } 
  98.                             } 
  99.                              
  100.                             field.setAccessible(true); 
  101.                             field.set(bean, value); 
  102.                         } 
  103.                     } 
  104.                 } catch (Exception e) { 
  105.                     e.printStackTrace(); 
  106.                 } 
  107.             } 
  108.         } 
  109.          
  110.     } 
  111.  
  112.     private void injectObject() { 
  113.         for(BeanDefinition beanDefinition : beanDefines){ 
  114.             // 得到  bean 。。 
  115.             Object bean = sigletons.get(beanDefinition.getId()); 
  116.             if(bean != null){ 
  117.                 try
  118.                     // 得到 bean的属性描述: 
  119.                     PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 
  120.                     // 循环  bean里面的 所有的属性: 
  121.                     for( PropertyDefinition propertyDefinition: beanDefinition.getPropertys()){ 
  122.                         for(PropertyDescriptor propertyDesc /*这里是 bean 里面的属性*/ : ps){ 
  123.                             if(propertyDefinition.getName().equals(propertyDesc.getName())){ 
  124.                                 // 如果相等 说明是存在 于 这个bean的。。。 
  125.                                 Method setter = propertyDesc.getWriteMethod();   // 获取属性的 setter方法。 
  126.                                 // 最好做一下判断: 
  127.                                 if(setter != null){ 
  128.                                      
  129.                                     Object value = null
  130.                                     if(propertyDefinition.getRef() != null && !"".equals(propertyDefinition.getRef().trim())){ 
  131.                                         // 注入依赖对象: 
  132.                                         value = sigletons.get(propertyDefinition.getRef()); 
  133.                                     }else
  134.                                         // 注入基本类型。。。把字符串的值  传换成  属性的值。 
  135.                                         value = ConvertUtils.convert(propertyDefinition.getValue(), propertyDesc.getPropertyType()); 
  136.                                     } 
  137.                                     setter.setAccessible(true); // 允许访问 私有的方法。。 
  138.                                     setter.invoke(bean, value);// 把引用对象注入到属性。 
  139.                                 } 
  140.                                 break
  141.                             } 
  142.                         } 
  143.                     } 
  144.                 } catch (Exception e) { 
  145.                     e.printStackTrace(); 
  146.                 } 
  147.             } 
  148.         } 
  149.     } 
  150.  
  151.     /**
  152.      * 通过反射技术,完成  bean 的实例化:
  153.      */ 
  154.     private void instanceBeans() { 
  155.         for(BeanDefinition beanDefinition : beanDefines){ 
  156.             try
  157.                 if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){ 
  158.                     sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance()); 
  159.                 } 
  160.             } catch (Exception e) { 
  161.                 e.printStackTrace(); 
  162.             } 
  163.         } 
  164.          
  165.     } 
  166.      
  167.  
  168.  
  169.     /**
  170.      * 读取  XML 的配置文件:
  171.      * @param fileName
  172.      */ 
  173.     @SuppressWarnings("unchecked"
  174.     private void readXML(String fileName) { 
  175.         // 创建读取器: 
  176.         SAXReader saxReader = new SAXReader(); 
  177.         Document document = null
  178.          
  179.         try
  180.             URL xmlPath = this.getClass().getClassLoader().getResource(fileName); 
  181.             document = saxReader.read(xmlPath); // 读取文件的内容。。。 
  182.              
  183.             Map<String,String> nsMap = new HashMap<String,String>(); 
  184.             nsMap.put("ns", "http://www.springframework.org/schema/beans"); // 加入命名空间 
  185.              
  186.             // 创建beans/bean 查询路径。 
  187.             XPath xsub = document.createXPath("//ns:beans/ns:bean");   
  188.              
  189.             // 设置命名空间。 
  190.             xsub.setNamespaceURIs(nsMap);                                  
  191.              
  192.             // 获取文档下 所有bean节点: 
  193.             List<Element> beans = xsub.selectNodes(document); 
  194.             for(Element element : beans){ 
  195.                 String id = element.attributeValue("id");             // 获取id属性值。 
  196.                 String clazz = element.attributeValue("class");       //  获取  class 属性值。 
  197.                 BeanDefinition beanDefine = new BeanDefinition(id, clazz); 
  198.                  
  199.                 // 查询的相对路径: 
  200.                 XPath propertysub = element.createXPath("ns:property"); 
  201.                 propertysub.setNamespaceURIs(nsMap);// 设置命名空间。 
  202.                  
  203.                 List<Element> propertys = propertysub.selectNodes(element); 
  204.                 for(Element property : propertys){ 
  205.                     String propertyName = property.attributeValue("name"); 
  206.                     String propertyRef = property.attributeValue("ref"); 
  207.                      
  208.                     String propertyValue = property.attributeValue("value"); 
  209.                      
  210.                     System.out.println(propertyName + "==" + propertyRef); 
  211.                     PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyRef, propertyValue); 
  212.                      
  213.                     // 放到  bean里面去: 
  214.                     beanDefine.getPropertys().add(propertyDefinition); 
  215.                      
  216.                 } 
  217.                 beanDefines.add(beanDefine); 
  218.             } 
  219.              
  220.         }catch(Exception e){ 
  221.             e.printStackTrace(); 
  222.         } 
  223.     } 
  224.  
  225.      
  226.     /**
  227.      * 获取  bean实例
  228.      * @param beanName
  229.      * @return
  230.      */ 
  231.     public Object getBean(String beanName){ 
  232.         return this.sigletons.get(beanName); 
  233.     } 
  234.      

3,

  1. /**
  2. * 1 解析属性。
  3. * 2 看看  在哪里 有注解。 
  4. * 3 看看 有没有 配置 name属性。如果没有,再怎么办?
  5. *
  6. * @author Administrator
  7. *
  8. */ 
  9.  
  10. @Retention(RetentionPolicy.RUNTIME)   // 运行期。 
  11. @Target( {ElementType.FIELD ,ElementType.METHOD})            // 指定在  字段 与 方法上。 
  12. public @interface ItmResource { 
  13.     public String name() default ""


验证:

在测试类中,换成:

  1. ItmClassPathXMLApplicationContext ctx = new ItmClassPathXMLApplicationContext("beans.xml"); 
  2.         PersonService personService = (PersonService) ctx.getBean("personService"); 
  3.         personService.save(); 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值