12_传智播客Spring2.5视频教程_编码剖析@Resource注解的实现原理

本文深入探讨了Spring框架中依赖注入(DI)的实现机制,包括XML配置与注解方式的DI过程,以及如何通过反射机制实现对象实例化与属性注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一篇的基础上新增程序如下

 

package eleven.spring.application;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import seven.spring.application.beandefinition.BeanDefinition;
import seven.spring.application.beandefinition.PropertyBeanDefinition;
import eleven.spring.xuxlResource.XuxlResource;

public class ClassPathXMLApplicationContext {

 private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
 private Map<String, Object> objsMap = new HashMap<String, Object>();
 private static Logger myLogger = Logger.getLogger(ClassPathXMLApplicationContext.class);

 public ClassPathXMLApplicationContext(String fileName)
   throws ClassNotFoundException, IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
  this.readXML(fileName);
  this.instanceBeans();
  this.annotationInject();
  this.injectObject();
 }
   
 private void annotationInject() throws IntrospectionException,
   IllegalArgumentException, IllegalAccessException,
   InvocationTargetException {

  // 循环容器里的对象
  for (String beanName : objsMap.keySet()) {
   Object bean = objsMap.get(beanName);
   if (null != bean) {

    // 等到对象的成员变量的信息
    PropertyDescriptor[] propertyDescriptors = Introspector
      .getBeanInfo(bean.getClass()).getPropertyDescriptors();
    for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

     // 等到成员变量的set方法
     Method set = propertyDescriptor.getWriteMethod();

     // 判断变量的set方法是否有注释解析
     if (null != set
       && set.isAnnotationPresent(XuxlResource.class)) {
      // 得到注释解析对象
      XuxlResource xuxlResource = set
        .getAnnotation(XuxlResource.class);
      String xuxlResourceName = xuxlResource.name();
      Object value = null;
      // 注释解析对象设置name属性
      if (null != xuxlResourceName
        && !"".equals(xuxlResourceName)) {
       value = objsMap.get(xuxlResourceName);
      } else {
       value = objsMap.get(propertyDescriptor.getName());
      }
      // 根据name 属性 注射不成功的话 试图根据类型注射
      if (value == null) {

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

        if (propertyDescriptor.getPropertyType()
          .isAssignableFrom(
            objsMap.get(key).getClass())) {
         value = objsMap.get(key);
         break;
        }
       }
      }
      set.setAccessible(true);
      set.invoke(bean, value);
     }
    }
    // 没有 给成员变量的set方法 声明注释解析
    // 给 成员变量 声明注释解析
    Field[] fields = bean.getClass().getDeclaredFields();
    for (Field field : fields) {

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

      // 得到注释解析 对象
      XuxlResource xuxlResource = field
        .getAnnotation(XuxlResource.class);
      String xuxlResourceName = xuxlResource.name();
                        Object fieldValue = null;
      // 注释解析对象设置name属性
      if (null != xuxlResourceName
        && !"".equals(xuxlResourceName)) {
       fieldValue = objsMap.get(xuxlResourceName);
      } else {
       fieldValue = objsMap.get(field.getName());
      }
      // 根据name 属性 注射不成功的话 试图根据类型注射
      if (fieldValue == null) {

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

        if (field.getType().isAssignableFrom(
          objsMap.get(key).getClass())) {
         fieldValue = objsMap.get(key);
         break;
        }
       }
      }
      // 字段一般是private的
      field.setAccessible(true);
      // 不是通过set方法
      field.set(bean, fieldValue);

     }
    }
   }
  }
 }

 //
 private void injectObject() {
  for (BeanDefinition beanDefinition : beanDefinitions) {
   // 将 已经实例化的对象 迭代
   Object bean = objsMap.get(beanDefinition.getId());
   // 要养成 对 对象判空的编码习惯
   if (null != bean){
    try {
     // 利用自反省机制获取成员变量, 继而获得对应的get set 方法
     PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
     
     for (PropertyBeanDefinition myPropertyBeanDefinition : beanDefinition.getPropertys()) {
      
      for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
       if (propertyDescriptor.getName().equals(myPropertyBeanDefinition.getName()) ){
        // 通过调用set方法 注入
        Method method = propertyDescriptor.getWriteMethod();
        if (null != method) {
         Object value = null;
         if(myPropertyBeanDefinition.getHref() != null &&"" != myPropertyBeanDefinition.getHref().trim()){
          value = objsMap.get(myPropertyBeanDefinition.getHref());
         } else{
          value = ConvertUtils.convert(myPropertyBeanDefinition.getValue(),propertyDescriptor.getPropertyType());
         }
         // 要养成 对 对象判空的编码习惯
         if (value != null) {
          method.setAccessible(true);
          method.invoke(bean, value);
         }
        }
       }
      }
     }
    } catch (Exception e) {
                    e.printStackTrace();
    }
   }
  }
 }
 private void instanceBeans() {
  
  myLogger.info(beanDefinitions.size());
  // 利用反射 生成类
  for (BeanDefinition beanDefinition : beanDefinitions) {
   String className = beanDefinition.getClassName();
   
   if (className != null && !"".equals(className.trim())) {
    try {
     // Class.forName(xxx.xx.xx) 返回的是一个类,
     // newInstance() 后才创建一个对象
     // Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类
     // ,也就是说JVM会执行该类的静态代码段
     myLogger.info(className);
     Object object = Class.forName(className).newInstance();
     objsMap.put(beanDefinition.getId(), object);
    } catch (Throwable e) {
     e.printStackTrace();
    }
   }
  }
 }

 private void readXML(String fileName) {
  
  SAXReader saxReader = new SAXReader();
  Document document = null;
  try {
           
   URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
   document = saxReader.read(xmlPath);
   Map<String, String> nsMap = new HashMap<String, String>();

   // 加入命名空间
   nsMap.put("ns", "http://www.springframework.org/schema/beans");

   // 创建beans/bean查询路径
   XPath xPath = document.createXPath("//ns:beans/ns:bean");

   // 设置命名空间
   xPath.setNamespaceURIs(nsMap);

   // 取得根元素下的所有节点
   List<Element> beans = xPath.selectNodes(document);
   for (Element element : beans) {
    
    String id = element.attributeValue("id");
    String clazz = element.attributeValue("class");
    myLogger.info(id);
    myLogger.info(clazz);
    BeanDefinition beanDefinition = new BeanDefinition(id, clazz);

    // 不需要 带根路径
    XPath xPathBeanDefinition = element.createXPath("ns:property");

    // 设置命名空间
    xPathBeanDefinition.setNamespaceURIs(nsMap);

    // 取得[Element]元素下的所有 节点
    List<Element> propertyBeans = xPathBeanDefinition.selectNodes(element);
    for (Element propertyBean : propertyBeans) {

     String name = propertyBean.attributeValue("name");
     String ref = propertyBean.attributeValue("ref");
     String value = propertyBean.attributeValue("value");
     
     PropertyBeanDefinition propertyDefination = new PropertyBeanDefinition(name);
     propertyDefination.setHref(ref);
     propertyDefination.setValue(value);
     beanDefinition.getPropertys().add(propertyDefination);
    }
    beanDefinitions.add(beanDefinition);
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }


 public List<BeanDefinition> getBeanDefinitions() {
  return beanDefinitions;
 }


 public void setBeanDefinitions(List<BeanDefinition> beanDefinitions) {
  this.beanDefinitions = beanDefinitions;
 }


 public Map<String, Object> getObjsMap() {
  return objsMap;
 }


 public void setObjsMap(Map<String, Object> objsMap) {
  this.objsMap = objsMap;
 }
}

 ##########################################################

关于 isAssignableFrom

isAssignableFrom

 public native boolean isAssignableFrom(Class cls)
判定 Class 对象表示的类或接口是否同参数指定的 Class 表示的类或接口相同,或是其父类或父接口。 如果成立则返回 true,否则返回 false。若该类是基类型类,且指定的类参数恰为此类则返回 true,否则返回 false。

特别地,通过标别转换或其扩展引用,此方法将测试指定的 Class 参数表示的类型能否转换为当前 Class 对象表示的类型,关于更详细信息,请参看 The Java Language Specification 的 5.1.1 和 5.1.4 节。

 

抛出: NullPointerException
如果指定的类参数为 null。

isAssignableFrom   是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。  
  通常调用格式是  
        Class1.isAssignableFrom(Class2)  
  调用者和参数都是   java.lang.Class   类型。  
     
  而   instanceof   是用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例。  
    格式是:   oo   instanceof   TypeName    
    第一个参数是对象实例名,第二个参数是具体的类名或接口名,例如   String,InputStream。  
   
  用下面的代码进行测试,我们就可以发现他们的不同之处  
   
  /*  
    *   Created   on   2005-1-29  
    */  
  package   lang.test;  
   
  import   junit.framework.TestCase;  
   
  /**  
    *   <title>   LangTest  
    *   <description>    
    *   <company>  
    *   @version    
    *   @since    
    *    
    *2005-1-29   16:19:28  
    */  
  public   class   LangTest   extends   TestCase  
  {  
  /**  
    *   Constructor   for   LangTest.  
    *   @param   name  
    */  
  public   LangTest(String   name)  
  {  
  super(name);  
  }  
   
  public   void   testIsAssignedFrom1()  
  {  
  assertTrue(   String.class.isAssignableFrom(Object.class));  
  }  
   
  public   void   testIsAssignedFrom2()  
  {  
  assertTrue(   Object.class.isAssignableFrom(Object.class));  
  }  
   
  public   void   testIsAssignedFrom3()  
  {  
  assertTrue(   Object.class.isAssignableFrom(String.class));  
  }  
   
  public   void   testInstanceOf1()  
  {  
  String   ss   =   "";  
  assertTrue(   ss   instanceof   Object);  
  }  
   
  public   void   testInstanceOf2()  
  {  
  Object   o   =   new   Object();  
  assertTrue(   o   instanceof   Object);  
  }  
  }   
   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值