java注解注入使用,利用自定义Java注解实现资源注入

最近做项目,需要利用java反射机制,获取实体类自定义注解的说明信息 1.自定义注解 package com.bjhy.platform.criminal.search.core.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang

转自:http://www.blogjava.net/jnbzwm/archive/2010/10/04/333720.html

这里是想介绍一下如何通过Java的注解机制,实现对bean资源的注入。主要介绍实现的方法,至于例子的实用性不必讨论。

需求:一个应用有两个数据库,分别为DB-A,DB-B。

假设持久层框架使用iBatis来实现,那么SqlMapClient对象在创建时,对于两个不同的DB连接要有两个不同的SqlMapClient对象,

假设我们有一个Service类为MyService.java,该类中有两个SqlMapClient对象sqlMapA、sqlMapB分别对应着DB-A、DB-B。

先看看我们的SqlMapClient.java类:(自定义SqlMapClient类,用来演示。)

va22am.gif import  java.util.Map;

va22am.gif

va22am.gif import  org.apache.commons.lang.builder.ToStringBuilder;

va22am.gif import  org.apache.commons.lang.builder.ToStringStyle;

va22am.gif

va22am.gif@SuppressWarnings( " unchecked " )

ym6JZn.gif public   class  SqlMapClient  {

zI73my.gif    public SqlMapClient(String s, String t) {

naMJvq.gif        sqlMap = s;

naMJvq.gif        type = t;

aaAVBz.gif    }

naMJvq.gif    

zI73my.gif    public SqlMapClient() {

aaAVBz.gif    }

naMJvq.gif

naMJvq.gif    private String type   = null;

naMJvq.gif

naMJvq.gif    private String sqlMap = null;

naMJvq.gif    // get、set方法 略

naMJvq.gif

naMJvq.gif    // 用于演示查询后返回一个String的返回结果

zI73my.gif    public String selectForObject(String sql, Map in) {

naMJvq.gif        return this.toString();

aaAVBz.gif    }

naMJvq.gif    

naMJvq.gif    @Override

zI73my.gif    public String toString() {

naMJvq.gif        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("sqlMap", sqlMap)

naMJvq.gif        .append("type", type).toString();

aaAVBz.gif    }

AbUn2q.gif}

MyService.java类实现:

va22am.gif import  java.util.Map;

va22am.gif

va22am.gif@SuppressWarnings( " unchecked " )

ym6JZn.gif public   class  MyService  {

naMJvq.gif    @DataSource(type="B", sqlMap="com/annotation/sql-map-config-B.xml")

naMJvq.gif    private SqlMapClient sqlMapB = null;

naMJvq.gif    

naMJvq.gif    @DataSource(type="A", sqlMap="com/annotation/sql-map-config-A.xml")

naMJvq.gif    private SqlMapClient sqlMapA = null;

naMJvq.gif    

naMJvq.gif    // get、set方法 略

naMJvq.gif

naMJvq.gif    // 模拟在DB-B数据库取得数据

zI73my.gif    public String selectForObjectFromB(String sql, Map in) {

naMJvq.gif        return sqlMapB.selectForObject("", null);

aaAVBz.gif    }

naMJvq.gif    

naMJvq.gif    // 模拟在DB-A数据库取得数据

zI73my.gif    public String selectForObjectFromA(String sql, Map in) {

naMJvq.gif        return sqlMapA.selectForObject("", null);

aaAVBz.gif    }

AbUn2q.gif}

接下来就是我们的注解类:DataSource.java

va22am.gif import  java.lang.annotation.ElementType;

va22am.gif import  java.lang.annotation.Retention;

va22am.gif import  java.lang.annotation.RetentionPolicy;

va22am.gif import  java.lang.annotation.Target;

va22am.gif

va22am.gif@Target(ElementType.FIELD)

va22am.gif@Retention(RetentionPolicy.RUNTIME)

ym6JZn.gif public  @ interface  DataSource  {

zI73my.gif    /**

naMJvq.gif     * Dao的类型

naMJvq.gif     * @return

aaAVBz.gif     */

naMJvq.gif    String type() default "A"; // 连接的数据库类型 A or B

naMJvq.gif    

naMJvq.gif    String sqlMap() default ""; // Sql-Map-Config文件的路径,用于加载iBatis的SqlMapClient对象

AbUn2q.gif}

定义资源注入的接口 IFieldWiring.java。

之所以这里要定义这个接口,是为了以后扩展用,我们很方便的定义更多的自定义注解。

va22am.gif IFieldWiring.java

va22am.gif

va22am.gif import  java.lang.annotation.Annotation;

va22am.gif import  java.lang.reflect.Field;

va22am.gif

ym6JZn.gif public   interface  IFieldWiring  {

naMJvq.gif    

naMJvq.gif    Class extends Annotation> annotationClass();

naMJvq.gif    

naMJvq.gif    void wiring(Object object, Field field);

AbUn2q.gif}

IFieldWiring.java的实现类----DataSourceWiring.java。(该类实现只为演示用,有很多地方是可以改进的)原帖:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法。 元注解:   元注解的作用就是负责

va22am.gif import  java.lang.annotation.Annotation;

va22am.gif import  java.lang.reflect.Field;

va22am.gif

ym6JZn.gif public   class  DataSourceWiring  implements  IFieldWiring {

naMJvq.gif

naMJvq.gif    @Override

zI73my.gif    public void wiring(Object object, Field field) {

naMJvq.gif        Object fieldObj = ReflectUtils.getFieldValue(object, field.getName()); // 获得field对应的对象

zI73my.gif        if (fieldObj != null) {

naMJvq.gif            return;

aaAVBz.gif        }

naMJvq.gif        DataSource annotation = field.getAnnotation(DataSource.class);

naMJvq.gif        String type = annotation.type();

naMJvq.gif        String sqlMap = annotation.sqlMap();

naMJvq.gif        // 这里可以用缓存来实现,不用每次都去创建新的SqlMapClient对象

naMJvq.gif        SqlMapClient sqlMapImpl = new SqlMapClient(sqlMap, type);

naMJvq.gif        // 将生成SqlMapClient注入到bean对象的字段上

naMJvq.gif        ReflectUtils.setFieldValue(object, field.getName(), SqlMapClient.class, sqlMapImpl);

aaAVBz.gif    }

naMJvq.gif

naMJvq.gif    @Override

zI73my.gif    public Class extends Annotation> annotationClass() {

naMJvq.gif        return DataSource.class;

aaAVBz.gif    }

AbUn2q.gif}

这里的ReflectUtils.java 也是我们自定义的,并非有Spring提供的:

va22am.gif import  java.lang.reflect.Field;

va22am.gif import  java.lang.reflect.Method;

va22am.gif

va22am.gif import  org.apache.commons.lang.StringUtils;

va22am.gif

ym6JZn.gif public   class  ReflectUtils  {

naMJvq.gif

zI73my.gif    /**

naMJvq.gif     * 取得字段值

naMJvq.gif     * 

naMJvq.gif     * @param obj

naMJvq.gif     * @param fieldName

naMJvq.gif     * @return

aaAVBz.gif     */

zI73my.gif    public static Object getFieldValue(Object obj, String fieldName) {

zI73my.gif        if (obj == null || fieldName == null || "".equals(fieldName)) {

naMJvq.gif            return null;

aaAVBz.gif        }

naMJvq.gif

naMJvq.gif        Class> clazz = obj.getClass();

zI73my.gif        try {

naMJvq.gif            String methodname = "get" + StringUtils.capitalize(fieldName);

naMJvq.gif            Method method = clazz.getDeclaredMethod(methodname);

naMJvq.gif            method.setAccessible(true);

naMJvq.gif            return method.invoke(obj);

zI73my.gif        } catch (Exception e) {

zI73my.gif            try {

naMJvq.gif                Field field = clazz.getDeclaredField(fieldName);

naMJvq.gif                field.setAccessible(true);

naMJvq.gif                return field.get(obj);

zI73my.gif            } catch (Exception e1) {

naMJvq.gif                e1.printStackTrace();

aaAVBz.gif            }

aaAVBz.gif        }

naMJvq.gif        return null;

aaAVBz.gif    }

naMJvq.gif

naMJvq.gif    public static void setFieldValue(Object target, String fname, Class> fieldClass,

zI73my.gif        Object fieldObj) {

zI73my.gif        if (!fieldClass.isAssignableFrom(fieldObj.getClass())) {

naMJvq.gif            return;

aaAVBz.gif        }

naMJvq.gif        Class> clazz = target.getClass();

zI73my.gif        try {

naMJvq.gif            Method method = clazz.getDeclaredMethod("set" + Character.toUpperCase(fname.charAt(0))

naMJvq.gif                + fname.substring(1), fieldClass);

naMJvq.gif            method.setAccessible(true);

naMJvq.gif            method.invoke(target, fieldObj);

zI73my.gif        } catch (Exception e) {

zI73my.gif            try {

naMJvq.gif                Field field = clazz.getDeclaredField(fname);

naMJvq.gif                field.setAccessible(true);

naMJvq.gif                field.set(target, fieldObj);

zI73my.gif            } catch (Exception e1) {

naMJvq.gif                e1.printStackTrace();

aaAVBz.gif            }

aaAVBz.gif        }

aaAVBz.gif    }

AbUn2q.gif}

已经基本大功告成了,只要将我们的DataSourceWiring.java类使用起来即可。

MyAnnotationBeanProcessor.java,这个类主要用于为bean对象注入资源。

va22am.gif import  java.lang.reflect.Field;

va22am.gif

ym6JZn.gif public   class  MyAnnotationBeanProcessor  {

naMJvq.gif

zI73my.gif    /**

naMJvq.gif     * 注入资源

naMJvq.gif     * @param serviceObject

naMJvq.gif     * @param fieldAutoWirings // 所有实现IFieldWiring的接口的对象,我们可以在此扩展

naMJvq.gif     * @throws Exception

aaAVBz.gif     */

naMJvq.gif    public void wire(Object serviceObject, IFieldWiring

6Vnauy.gif fieldAutoWirings)

zI73my.gif            throws Exception {

naMJvq.gif        Class> cls = serviceObject.getClass();

zI73my.gif        for (Field field : cls.getDeclaredFields()) {

zI73my.gif            for (IFieldWiring fieldAutoWiring : fieldAutoWirings) {

zI73my.gif                if (field.isAnnotationPresent(fieldAutoWiring.annotationClass())) {

naMJvq.gif                    fieldAutoWiring.wiring(serviceObject, field);

naMJvq.gif                    break;

aaAVBz.gif                }

aaAVBz.gif            }

aaAVBz.gif        }

aaAVBz.gif    }

AbUn2q.gif}

好了,开始我们的测试类:FieldWiringTest.java

ym6JZn.gif public   class  FieldWiringTest  {

zI73my.gif    public static void main(String args[]) throws Exception {

naMJvq.gif        MyAnnotationBeanProcessor processor = new MyAnnotationBeanProcessor();

naMJvq.gif

naMJvq.gif        MyService b = new MyService();

naMJvq.gif

naMJvq.gif        processor.wire(b, new DataSourceWiring()); // 注入DataSource资源

naMJvq.gif        

naMJvq.gif        System.out.println(b.selectForObjectFromB("", null));

naMJvq.gif        System.out.println(b.selectForObjectFromA("", null));

aaAVBz.gif    }

AbUn2q.gif}

执行结果:

va22am.gif SqlMapClient[sqlMap = com / annotation / sql - map - config - B.xml,type = B]

va22am.gifSqlMapClient[sqlMap = com / annotation / sql - map - config - A.xml,type = A]

由执行结果可以说明DataSource资源已经被我们正确的注入了。

如果想扩展的话,只需要新建一个类实现IFieldWiring接口即可。假设叫InParamWiring.java,实现了接口定义的两个方法后,在使用的时候,只要用以下代码便可将资源注入了:

va22am.gif MyAnnotationBeanProcessor processor  =   new  MyAnnotationBeanProcessor();

va22am.gifMyService b  =   new  MyService();

va22am.gifprocessor.wire(b,  new  DataSourceWiring(),  new  InParamWiring());  //  注入DataSource、InParam资源

注:以上代码重在演示,其实这个需求可以在Spring中管理两个不同的SqlMapClient对象,然后通过Spring的自动注入实现。

下一篇将介绍怎么通过Spring实现这样的自定义资源注入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值