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

 import com.annotation.MyService;
import com.annotation.MyService;


 public class SpringWiringTest
public class SpringWiringTest  {
{

 public static void main(String args[])
    public static void main(String args[])  {
{
 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/spring/applicationContext.xml");
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/spring/applicationContext.xml");
 MyService b = (MyService)ctx.getBean("myService"); // 通过Spring去管理bean,此时已完成了对标有DataSource注解的资源的注入
        MyService b = (MyService)ctx.getBean("myService"); // 通过Spring去管理bean,此时已完成了对标有DataSource注解的资源的注入
 System.out.println(b.selectForObjectFromB("", null));
        System.out.println(b.selectForObjectFromB("", null));
 System.out.println(b.selectForObjectFromA("", null));
        System.out.println(b.selectForObjectFromA("", null));
 }
    }
 }
}
注:MyService类实现在 
利用自定义Java注解实现资源注入 中。
为了实现上面的目标,我们就不能使用MyAnnotationBeanProcessor.java类来实现对资源的注入了,我们必须实现一个能融入Spring的BeanProcessor类才行。
DataSourceBeanProcessor.java类实现BeanPostProcessor、PriorityOrdered接口:
 import java.lang.reflect.Field;
import java.lang.reflect.Field;

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


 public class DataSourceBeanProcessor implements BeanPostProcessor, PriorityOrdered
public class DataSourceBeanProcessor implements BeanPostProcessor, PriorityOrdered  {
{
 @Override
    @Override
 // 在这里完成资源注入
    // 在这里完成资源注入
 public Object postProcessAfterInitialization(Object bean, String beanName)
    public Object postProcessAfterInitialization(Object bean, String beanName)

 throws BeansException
        throws BeansException  {
{
 Class<?> cls = bean.getClass();
        Class<?> cls = bean.getClass();

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

 if (field.isAnnotationPresent(DataSource.class))
            if (field.isAnnotationPresent(DataSource.class))  {
{
 DataSourceStaticWiring.wiring(bean, field);
                DataSourceStaticWiring.wiring(bean, field);
 }
            }
 }
        }
 return bean;
        return bean;
 }
    }

 @Override
    @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName)
    public Object postProcessBeforeInitialization(Object bean, String beanName)

 throws BeansException
        throws BeansException  {
{
 return bean;
        return bean;
 }
    }

 @Override
    @Override

 public int getOrder()
    public int getOrder()  {
{
 return Ordered.LOWEST_PRECEDENCE;
        return Ordered.LOWEST_PRECEDENCE;
 }
    }
 }
}
下面来看DataSourceStaticWiring的实现,与前一篇 里的DataSourceWiring.java类相比,改动点有以下三个:
1.不需要实现IFieldWiring接口
2.删除annotationClass方法
3.将wiring方法修改为static方法
具体代码如下:
 import java.lang.reflect.Field;
import java.lang.reflect.Field;


 public class DataSourceStaticWiring
public class DataSourceStaticWiring  {
{


 public static void wiring(Object object, Field field)
    public static void wiring(Object object, Field field)  {
{
 Object fieldObj = ReflectUtils.getFieldValue(object, field.getName());
        Object fieldObj = ReflectUtils.getFieldValue(object, field.getName());

 if (fieldObj != null)
        if (fieldObj != null)  {
{
 return;
            return;
 }
        }
 DataSource annotation = field.getAnnotation(DataSource.class);
        DataSource annotation = field.getAnnotation(DataSource.class);
 String type = annotation.type();
        String type = annotation.type();
 String sqlMap = annotation.sqlMap();
        String sqlMap = annotation.sqlMap();
 // 这里可以用缓存来实现,不用每次都去创建新的SqlMapClient对象
        // 这里可以用缓存来实现,不用每次都去创建新的SqlMapClient对象
 SqlMapClient sqlMapImpl = new SqlMapClient(sqlMap, type);
        SqlMapClient sqlMapImpl = new SqlMapClient(sqlMap, type);
 ReflectUtils.setFieldValue(object, field.getName(), SqlMapClient.class, sqlMapImpl);
        ReflectUtils.setFieldValue(object, field.getName(), SqlMapClient.class, sqlMapImpl);
 }
    }
 }
}
注:SqlMapClient、ReflectUtils实现在上一篇 
利用自定义Java注解实现资源注入 中。
代码已准备就绪,接下来是配置Spring:applicationContext.xml
 <?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
    xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop 
 http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
 http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx 
 http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
 http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-2.5.xsd"
           http://www.springframework.org/schema/context/spring-context-2.5.xsd"
 default-lazy-init="true">
    default-lazy-init="true">
 
    
 <!-- 自定义的BeanProcessor -->
    <!-- 自定义的BeanProcessor -->
 <bean class="com.annotation.DataSourceBeanProcessor" />
    <bean class="com.annotation.DataSourceBeanProcessor" />
 <context:component-scan base-package="com.annotation" />
    <context:component-scan base-package="com.annotation" />

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

测试代码其实已经在前面列出来了。SpringWiringTest.java
 import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

 import com.annotation.MyService;
import com.annotation.MyService;


 public class SpringWiringTest
public class SpringWiringTest  {
{

 public static void main(String args[])
    public static void main(String args[])  {
{
 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/spring/applicationContext.xml");
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/spring/applicationContext.xml");
 MyService b = (MyService)ctx.getBean("myService");
        MyService b = (MyService)ctx.getBean("myService");
 System.out.println(b.selectForObjectFromB("", null));
        System.out.println(b.selectForObjectFromB("", null));
 System.out.println(b.selectForObjectFromA("", 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-B.xml,type=B]
 SqlMapClient[sqlMap=com/annotation/sql-map-config-A.xml,type=A]
SqlMapClient[sqlMap=com/annotation/sql-map-config-A.xml,type=A]
由结果可见,我们利用Spring完成了对DataSource资源的注入了。
在这里如果还想扩展的话,就需要新建类假设为InParamBeanProcessor,实现BeanPostProcessor、PriorityOrdered接口,然后实现其中的方法,对资源进行注入,这里就是扩展Spring了,与本篇介绍的方法相同。
注:以上代码重在演示,其实这个需求可以在Spring中管理两个不同的SqlMapClient对象,然后通过Spring的自动注入实现。
本文为原创,欢迎转载,转载请注明出处
BlogJava。