利用自定义Java注解实现资源注入
2012-09-05 15:46
501 查看
这里是想介绍一下如何通过Java的注解机制,实现对bean资源的注入。主要介绍实现的方法,至于例子的实用性不必讨论。
需求:一个应用有两个数据库,分别为DB-A,DB-B。
假设持久层框架使用iBatis来实现,那么SqlMapClient对象在创建时,对于两个不同的DB连接要有两个不同的SqlMapClient对象,
假设我们有一个Service类为MyService.java,该类中有两个SqlMapClient对象sqlMapA、sqlMapB分别对应着DB-A、DB-B。
先看看我们的SqlMapClient.java类:(自定义SqlMapClient类,用来演示。)
MyService.java类实现:
接下来就是我们的注解类:DataSource.java
定义资源注入的接口 IFieldWiring.java。
之所以这里要定义这个接口,是为了以后扩展用,我们很方便的定义更多的自定义注解。
IFieldWiring.java的实现类----DataSourceWiring.java。(该类实现只为演示用,有很多地方是可以改进的)
这里的ReflectUtils.java 也是我们自定义的,并非有Spring提供的:
已经基本大功告成了,只要将我们的DataSourceWiring.java类使用起来即可。
MyAnnotationBeanProcessor.java,这个类主要用于为bean对象注入资源。
好了,开始我们的测试类:FieldWiringTest.java
执行结果:
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实现这样的自定义资源注入。
转载地址:http://www.fengfly.com/plus/view-191036-1.html
需求:一个应用有两个数据库,分别为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实现这样的自定义资源注入。
转载地址:http://www.fengfly.com/plus/view-191036-1.html
相关文章推荐
- 利用Spring的AOP编程和JAVA自定义注解,实现Web项目的HTTP请求头域检测
- 通过Spring实现对自定义注解属性进行资源注入
- Java利用自定义注解、反射实现简单BaseDao实例
- JAVAWEB开发之Servlet3.0新特性的使用以及注解的详细使用和自定义注解的方法、动态代理的使用、利用动态代理实现细粒度的权限控制以及类加载和泛型反射
- 【Java】利用注解和反射实现一个"低配版"的依赖注入
- Java注解实现原理及自定义注解
- ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存
- Java注解详解,自定义注解,利用反射解析注解
- java 自定义注解注入父类属性值
- java自定义注解接口实现方案
- Java注解详解,自定义注解,利用反射解析注解
- Java 自定义注解实现ORM对象关系映射
- Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录
- java利用注解实现简单的excel数据读取
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- spring源码剖析(五)利用AOP实现自定义Spring注解
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- Java注解教程:自定义注解示例,利用反射进行解析
- 通过自定义注解利用AOP在springmvc中实现记录日志
- java 自定义注解 spring aop 实现注解