ALL is Well!

          敏捷是一條很長的路,摸索著前進(jìn)著

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            30 隨筆 :: 23 文章 :: 71 評論 :: 0 Trackbacks
          <2010年10月>
          262728293012
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          公告

          聲明:本博客文章如無特別注明,均為原創(chuàng),作者保留所有權(quán)利!歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處BlogJava

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          交流社區(qū)

          友情鏈接

          學(xué)習(xí)資源庫

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          這里是想介紹一下如何通過Java的注解機(jī)制,實(shí)現(xiàn)對bean資源的注入。主要介紹實(shí)現(xiàn)的方法,至于例子的實(shí)用性不必討論。
          需求:一個(gè)應(yīng)用有兩個(gè)數(shù)據(jù)庫,分別為DB-A,DB-B。
          假設(shè)持久層框架使用iBatis來實(shí)現(xiàn),那么SqlMapClient對象在創(chuàng)建時(shí),對于兩個(gè)不同的DB連接要有兩個(gè)不同的SqlMapClient對象,
          假設(shè)我們有一個(gè)Service類為MyService.java,該類中有兩個(gè)SqlMapClient對象sqlMapA、sqlMapB分別對應(yīng)著DB-A、DB-B。

          先看看我們的SqlMapClient.java類:(自定義SqlMapClient類,用來演示。)
          import java.util.Map;

          import org.apache.commons.lang.builder.ToStringBuilder;
          import org.apache.commons.lang.builder.ToStringStyle;

          @SuppressWarnings(
          "unchecked")
          public class SqlMapClient {
              
          public SqlMapClient(String s, String t) {
                  sqlMap 
          = s;
                  type 
          = t;
              }

              
              
          public SqlMapClient() {
              }


              
          private String type   = null;

              
          private String sqlMap = null;
              
          // get、set方法 略

              
          // 用于演示查詢后返回一個(gè)String的返回結(jié)果
              public String selectForObject(String sql, Map in) {
                  
          return this.toString();
              }

              
              @Override
              
          public String toString() {
                  
          return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("sqlMap", sqlMap)
                  .append(
          "type", type).toString();
              }

          }

          MyService.java類實(shí)現(xiàn):
          import java.util.Map;

          @SuppressWarnings(
          "unchecked")
          public class MyService {
              @DataSource(type
          ="B", sqlMap="com/annotation/sql-map-config-B.xml")
              
          private SqlMapClient sqlMapB = null;
              
              @DataSource(type
          ="A", sqlMap="com/annotation/sql-map-config-A.xml")
              
          private SqlMapClient sqlMapA = null;
              
              
          // get、set方法 略

              
          // 模擬在DB-B數(shù)據(jù)庫取得數(shù)據(jù)
              public String selectForObjectFromB(String sql, Map in) {
                  
          return sqlMapB.selectForObject(""null);
              }

              
              
          // 模擬在DB-A數(shù)據(jù)庫取得數(shù)據(jù)
              public String selectForObjectFromA(String sql, Map in) {
                  
          return sqlMapA.selectForObject(""null);
              }

          }

          接下來就是我們的注解類:DataSource.java
          import java.lang.annotation.ElementType;
          import java.lang.annotation.Retention;
          import java.lang.annotation.RetentionPolicy;
          import java.lang.annotation.Target;

          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface DataSource {
              
          /**
               * Dao的類型
               * 
          @return
               
          */

              String type() 
          default "A"// 連接的數(shù)據(jù)庫類型 A or B
              
              String sqlMap() 
          default ""// Sql-Map-Config文件的路徑,用于加載iBatis的SqlMapClient對象
          }

          定義資源注入的接口 IFieldWiring.java。
          之所以這里要定義這個(gè)接口,是為了以后擴(kuò)展用,我們很方便的定義更多的自定義注解。
          IFieldWiring.java

          import java.lang.annotation.Annotation;
          import java.lang.reflect.Field;

          public interface IFieldWiring {
              
              Class
          <? extends Annotation> annotationClass();
              
              
          void wiring(Object object, Field field);
          }

          IFieldWiring.java的實(shí)現(xiàn)類----DataSourceWiring.java。(該類實(shí)現(xiàn)只為演示用,有很多地方是可以改進(jìn)的)
          import java.lang.annotation.Annotation;
          import java.lang.reflect.Field;

          public class DataSourceWiring implements IFieldWiring{

              @Override
              
          public void wiring(Object object, Field field) {
                  Object fieldObj 
          = ReflectUtils.getFieldValue(object, field.getName()); // 獲得field對應(yīng)的對象
                  if (fieldObj != null{
                      
          return;
                  }

                  DataSource annotation 
          = field.getAnnotation(DataSource.class);
                  String type 
          = annotation.type();
                  String sqlMap 
          = annotation.sqlMap();
                  
          // 這里可以用緩存來實(shí)現(xiàn),不用每次都去創(chuàng)建新的SqlMapClient對象
                  SqlMapClient sqlMapImpl = new SqlMapClient(sqlMap, type);
                  
          // 將生成SqlMapClient注入到bean對象的字段上
                  ReflectUtils.setFieldValue(object, field.getName(), SqlMapClient.class, sqlMapImpl);
              }


              @Override
              
          public Class<? extends Annotation> annotationClass() {
                  
          return DataSource.class;
              }

          }

          這里的ReflectUtils.java 也是我們自定義的,并非有Spring提供的:
          import java.lang.reflect.Field;
          import java.lang.reflect.Method;

          import org.apache.commons.lang.StringUtils;

          public class ReflectUtils {

              
          /**
               * 取得字段值
               * 
               * 
          @param obj
               * 
          @param fieldName
               * 
          @return
               
          */

              
          public static Object getFieldValue(Object obj, String fieldName) {
                  
          if (obj == null || fieldName == null || "".equals(fieldName)) {
                      
          return null;
                  }


                  Class
          <?> clazz = obj.getClass();
                  
          try {
                      String methodname 
          = "get" + StringUtils.capitalize(fieldName);
                      Method method 
          = clazz.getDeclaredMethod(methodname);
                      method.setAccessible(
          true);
                      
          return method.invoke(obj);
                  }
           catch (Exception e) {
                      
          try {
                          Field field 
          = clazz.getDeclaredField(fieldName);
                          field.setAccessible(
          true);
                          
          return field.get(obj);
                      }
           catch (Exception e1) {
                          e1.printStackTrace();
                      }

                  }

                  
          return null;
              }


              
          public static void setFieldValue(Object target, String fname, Class<?> fieldClass,
                  Object fieldObj) 
          {
                  
          if (!fieldClass.isAssignableFrom(fieldObj.getClass())) {
                      
          return;
                  }

                  Class
          <?> clazz = target.getClass();
                  
          try {
                      Method method 
          = clazz.getDeclaredMethod("set" + Character.toUpperCase(fname.charAt(0))
                          
          + fname.substring(1), fieldClass);
                      method.setAccessible(
          true);
                      method.invoke(target, fieldObj);
                  }
           catch (Exception e) {
                      
          try {
                          Field field 
          = clazz.getDeclaredField(fname);
                          field.setAccessible(
          true);
                          field.set(target, fieldObj);
                      }
           catch (Exception e1) {
                          e1.printStackTrace();
                      }

                  }

              }

          }

          已經(jīng)基本大功告成了,只要將我們的DataSourceWiring.java類使用起來即可。
          MyAnnotationBeanProcessor.java,這個(gè)類主要用于為bean對象注入資源。
          import java.lang.reflect.Field;

          public class MyAnnotationBeanProcessor {

              
          /**
               * 注入資源
               * 
          @param serviceObject
               * 
          @param fieldAutoWirings // 所有實(shí)現(xiàn)IFieldWiring的接口的對象,我們可以在此擴(kuò)展
               * 
          @throws Exception
               
          */

              
          public void wire(Object serviceObject, IFieldWiring fieldAutoWirings)
                      
          throws Exception {
                  Class
          <?> cls = serviceObject.getClass();
                  
          for (Field field : cls.getDeclaredFields()) {
                      
          for (IFieldWiring fieldAutoWiring : fieldAutoWirings) {
                          
          if (field.isAnnotationPresent(fieldAutoWiring.annotationClass())) {
                              fieldAutoWiring.wiring(serviceObject, field);
                              
          break;
                          }

                      }

                  }

              }

          }

          好了,開始我們的測試類:FieldWiringTest.java
          public class FieldWiringTest {
              
          public static void main(String args[]) throws Exception {
                  MyAnnotationBeanProcessor processor 
          = new MyAnnotationBeanProcessor();

                  MyService b 
          = new MyService();

                  processor.wire(b, 
          new DataSourceWiring()); // 注入DataSource資源
                  
                  System.out.println(b.selectForObjectFromB(
          ""null));
                  System.out.println(b.selectForObjectFromA(
          ""null));
              }

          }

          執(zhí)行結(jié)果:
          SqlMapClient[sqlMap=com/annotation/sql-map-config-B.xml,type=B]
          SqlMapClient[sqlMap
          =com/annotation/sql-map-config-A.xml,type=A]

          由執(zhí)行結(jié)果可以說明DataSource資源已經(jīng)被我們正確的注入了。
          如果想擴(kuò)展的話,只需要新建一個(gè)類實(shí)現(xiàn)IFieldWiring接口即可。假設(shè)叫InParamWiring.java,實(shí)現(xiàn)了接口定義的兩個(gè)方法后,在使用的時(shí)候,只要用以下代碼便可將資源注入了:
          MyAnnotationBeanProcessor processor = new MyAnnotationBeanProcessor();
          MyService b 
          = new MyService();
          processor.wire(b, 
          new DataSourceWiring(), new InParamWiring()); // 注入DataSource、InParam資源

          注:以上代碼重在演示,其實(shí)這個(gè)需求可以在Spring中管理兩個(gè)不同的SqlMapClient對象,然后通過Spring的自動(dòng)注入實(shí)現(xiàn)。
          下一篇將介紹怎么通過Spring實(shí)現(xiàn)這樣的自定義資源注入。


          本文為原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處BlogJava
          posted on 2010-10-04 10:19 李 明 閱讀(5351) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 德阳市| 赤水市| 镇沅| 凤冈县| 佛学| 大余县| 寿阳县| 康乐县| 始兴县| 宣武区| 蓝田县| 内江市| 灯塔市| 沂南县| 井研县| 密云县| 长海县| 建湖县| 长泰县| 将乐县| 丰顺县| 恩施市| 南汇区| 连云港市| 屏南县| 广昌县| 永安市| 秀山| 湟源县| 资兴市| 阿尔山市| 晋宁县| 郧西县| 岳普湖县| 呼图壁县| 全椒县| 彰化市| 弋阳县| 石棉县| 常山县| 大悟县|