<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    ALL is Well!

    敏捷是一條很長的路,摸索著前進著

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      30 隨筆 :: 23 文章 :: 71 評論 :: 0 Trackbacks
    這里是想介紹一下如何通過Java的注解機制,實現對bean資源的注入。主要介紹實現的方法,至于例子的實用性不必討論。
    需求:一個應用有兩個數據庫,分別為DB-A,DB-B。
    假設持久層框架使用iBatis來實現,那么SqlMapClient對象在創建時,對于兩個不同的DB連接要有兩個不同的SqlMapClient對象,
    假設我們有一個Service類為MyService.java,該類中有兩個SqlMapClient對象sqlMapA、sqlMapB分別對應著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方法 略

        
    // 用于演示查詢后返回一個String的返回結果
        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類實現:
    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數據庫取得數據
        public String selectForObjectFromB(String sql, Map in) {
            
    return sqlMapB.selectForObject(""null);
        }

        
        
    // 模擬在DB-A數據庫取得數據
        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"// 連接的數據庫類型 A or B
        
        String sqlMap() 
    default ""// Sql-Map-Config文件的路徑,用于加載iBatis的SqlMapClient對象
    }

    定義資源注入的接口 IFieldWiring.java。
    之所以這里要定義這個接口,是為了以后擴展用,我們很方便的定義更多的自定義注解。
    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的實現類----DataSourceWiring.java。(該類實現只為演示用,有很多地方是可以改進的)
    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對應的對象
            if (fieldObj != null{
                
    return;
            }

            DataSource annotation 
    = field.getAnnotation(DataSource.class);
            String type 
    = annotation.type();
            String sqlMap 
    = annotation.sqlMap();
            
    // 這里可以用緩存來實現,不用每次都去創建新的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();
                }

            }

        }

    }

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

    public class MyAnnotationBeanProcessor {

        
    /**
         * 注入資源
         * 
    @param serviceObject
         * 
    @param fieldAutoWirings // 所有實現IFieldWiring的接口的對象,我們可以在此擴展
         * 
    @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));
        }

    }

    執行結果:
    SqlMapClient[sqlMap=com/annotation/sql-map-config-B.xml,type=B]
    SqlMapClient[sqlMap
    =com/annotation/sql-map-config-A.xml,type=A]

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

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


    本文為原創,歡迎轉載,轉載請注明出處BlogJava
    posted on 2010-10-04 10:19 李 明 閱讀(5349) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 4444亚洲国产成人精品| 最近2022中文字幕免费视频 | 成年性生交大片免费看 | 亚洲爆乳精品无码一区二区| 国产一区二区三区免费在线观看| 亚洲狠狠ady亚洲精品大秀| 成人免费午夜视频| 三年片免费高清版| 国产成人精品日本亚洲专一区| 2019中文字幕在线电影免费| 西西人体44rt高清亚洲| 两性色午夜免费视频| 7777久久亚洲中文字幕| 亚洲精品亚洲人成在线观看| 色www永久免费| 国产成A人亚洲精V品无码| 成年人免费观看视频网站| 国产成人免费ā片在线观看老同学| 亚洲乱码一区av春药高潮| 老司机在线免费视频| 亚洲国产精品成人精品软件 | 亚洲欧洲成人精品香蕉网| 四虎成人免费大片在线| 久久久久久国产精品免费免费男同 | 亚洲日本va在线观看| 最新亚洲成av人免费看| 成人免费777777被爆出| 久久亚洲国产最新网站| 久久精品亚洲一区二区| www.91亚洲| 成人免费av一区二区三区| 亚洲精华国产精华精华液好用| 久久亚洲国产精品| 亚洲偷自拍拍综合网| 无码人妻精品一二三区免费| 久久久久国产免费| 中国内地毛片免费高清| 免费很黄无遮挡的视频毛片| 国产亚洲精品看片在线观看| 日韩激情无码免费毛片| 亚欧乱色国产精品免费视频|