通过Spring实现对自定义注解属性进行资源注入

通过上一篇 利用自定义Java注解实现资源注入 介绍的方法,我们实现了通过自定义注解完成了对DataSource资源的注入,但在实际应用中,我们通常不希望去显式的去声明这样的MyAnnotationBeanProcessor对象来帮助我们完成注入,而是希望通过Spring帮我们“悄悄地”完成。
继 利用自定义Java注解实现资源注入 里的代码(部分代码)不变,我们希望在测试类中以如下方法调用便可以实现资源的注入:


import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.annotation.MyService;

public class SpringWiringTest {
public static void main(String args[]) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/spring/applicationContext.xml");
MyService b = (MyService)ctx.getBean("myService"); // 通过Spring去管理bean,此时已完成了对标有DataSource注解的资源的注入
System.out.println(b.selectForObjectFromB("", null));
System.out.println(b.selectForObjectFromA("", null));
}
}


注:MyService类实现在 利用自定义Java注解实现资源注入 中。

为了实现上面的目标,我们就不能使用MyAnnotationBeanProcessor.java类来实现对资源的注入了,我们必须实现一个能融入Spring的BeanProcessor类才行。
DataSourceBeanProcessor.java类实现BeanPostProcessor、PriorityOrdered接口:


import java.lang.reflect.Field;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;

public class DataSourceBeanProcessor implements BeanPostProcessor, PriorityOrdered {
@Override
// 在这里完成资源注入
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
Class<?> cls = bean.getClass();
for (Field field : cls.getDeclaredFields()) {
if (field.isAnnotationPresent(DataSource.class)) {
DataSourceStaticWiring.wiring(bean, field);
}
}
return bean;
}

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}

@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}


下面来看DataSourceStaticWiring的实现,与前一篇 里的DataSourceWiring.java类相比,改动点有以下三个:
1.不需要实现IFieldWiring接口
2.删除annotationClass方法
3.将wiring方法修改为static方法
具体代码如下:


import java.lang.reflect.Field;

public class DataSourceStaticWiring {

public static void wiring(Object object, Field field) {
Object fieldObj = ReflectUtils.getFieldValue(object, field.getName());
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);
ReflectUtils.setFieldValue(object, field.getName(), SqlMapClient.class, sqlMapImpl);
}
}


注:SqlMapClient、ReflectUtils实现在上一篇 利用自定义Java注解实现资源注入 中。

代码已准备就绪,接下来是配置Spring:applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-lazy-init="true">

<!-- 自定义的BeanProcessor -->
<bean class="com.annotation.DataSourceBeanProcessor" />
<context:component-scan base-package="com.annotation" />

<!-- 测试用bean -->
<bean id="myService" class="com.annotation.MyService" destroy-method="close">
</bean>
</beans>


测试代码其实已经在前面列出来了。SpringWiringTest.java


import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.annotation.MyService;

public class SpringWiringTest {
public static void main(String args[]) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/spring/applicationContext.xml");
MyService b = (MyService)ctx.getBean("myService");
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]


由结果可见,我们利用Spring完成了对DataSource资源的注入了。

在这里如果还想扩展的话,就需要新建类假设为InParamBeanProcessor,实现BeanPostProcessor、PriorityOrdered接口,然后实现其中的方法,对资源进行注入,这里就是扩展Spring了,与本篇介绍的方法相同。

注:以上代码重在演示,其实这个需求可以在Spring中管理两个不同的SqlMapClient对象,然后通过Spring的自动注入实现。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值