<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
    主站蜘蛛池模板: 免费人成在线观看视频高潮| 国产精品高清全国免费观看| 中文字幕无码亚洲欧洲日韩| 狠狠久久永久免费观看| 日本永久免费a∨在线视频| 亚洲AV无码成人精品区蜜桃| 日韩精品福利片午夜免费观着| 边摸边吃奶边做爽免费视频网站 | 亚洲综合精品香蕉久久网| 午夜不卡久久精品无码免费| 亚洲字幕AV一区二区三区四区| 亚洲精品动漫人成3d在线| 亚洲毛片在线免费观看| 老外毛片免费视频播放| 亚洲精品午夜在线观看| 亚洲国产天堂久久综合| 国产免费不卡视频| 在线观看免费黄色网址| 亚洲Av永久无码精品黑人 | 免费鲁丝片一级在线观看| 三上悠亚在线观看免费| 97久久国产亚洲精品超碰热| 亚洲精品无码av人在线观看 | 91香焦国产线观看看免费| 日韩国产精品亚洲а∨天堂免| 亚洲伊人久久大香线蕉苏妲己| 亚洲av日韩片在线观看| 18国产精品白浆在线观看免费| 国产精品玖玖美女张开腿让男人桶爽免费看| 亚洲国产成a人v在线| 国产亚洲人成网站在线观看不卡| 免费毛片网站在线观看| 99久久免费国产香蕉麻豆 | 久久久国产精品无码免费专区| 黄网站色视频免费观看45分钟| 亚洲国产成人精品青青草原| 亚洲香蕉网久久综合影视| 四虎永久成人免费影院域名| 无码日韩人妻av一区免费| 97在线视频免费播放| 91视频免费观看|