通過上一篇
利用自定義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的自動注入實現。
本文為原創,歡迎轉載,轉載請注明出處
BlogJava。