Never give up!

如果说软件开发是一条布满荆棘的坎坷之路,那么我会每天在这道路两旁书上“火焰舞者,到此一游!”。

 

Inject Bean By Annotation

Spring IoC容器允许BeanFactoryPostProcessor在容器实际实例化任何其它的bean之前读取配置元数据,并有可能修改它。本文就是以annotation的方式对bean进行依赖注入。

代码如下:
Annotation

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;

@Target(
{METHOD, FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Inject {
    
// 默认注入方式是byName
    String value() default "";
}

BeanFactoryPostProcessor

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.CannotLoadBeanClassException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;

public class InjectProcessor implements BeanFactoryPostProcessor {

    
public void postProcessBeanFactory(
            ConfigurableListableBeanFactory configurablelistablebeanfactory)
            
throws BeansException {
        
        String[] beanDefinitionNames 
= configurablelistablebeanfactory.getBeanDefinitionNames();
        
        BeanDefinition beanDefinition 
= null;
        MutablePropertyValues propertyValues 
= null;
        Method method 
= null;
        Inject inject 
= null;
        String propertyName 
= null;
        
        
for (String beanDefinitionName : beanDefinitionNames) {
            beanDefinition 
= configurablelistablebeanfactory.getBeanDefinition(beanDefinitionName);
            
            
if (beanDefinition.isAbstract())
                
continue;
            
            
// 返回指定Bean定义信息的属性集合,此集合在bean factory post-processing期间可以被修改�
            propertyValues = beanDefinition.getPropertyValues();
            
            
/*
             * 找回指定类的属�性�描述(PropertyDescriptor)列表
             * PropertyDescriptor主要描述�一个属性和此属性的�一对访问方�法(getter and setter)
             
*/

            
for (PropertyDescriptor descriptor : BeanUtils.getPropertyDescriptors(
                    getBeanClassByName(beanDefinitionName, beanDefinition))) 
{
                
// 属�性�集合中已经存在此属性则返回
                if (propertyValues.getPropertyValue(propertyName = descriptor.getName()) != null
                    
continue;
                
                
// 属性�描述类中有写方法(setter)并且指定方法上有注解标记
                if ((method = descriptor.getWriteMethod()) != null
                        
&& (inject = AnnotationUtils.getAnnotation(method, Inject.class)) != null{
                    
// 关联Bean的名�称
                    String targetBeanName = StringUtils.hasText(inject
                            .value()) 
? inject.value() : propertyName;
                    
// 建立关联Bean的属性类        
                    propertyValues.addPropertyValue(new PropertyValue(propertyName,
                            
new RuntimeBeanReference(targetBeanName)));
                }

            }

        }

    }


    
/**
     * 根据Bean定义信息名得到Bean Class
     * 
     * 
@param name Bean定义信息名称
     * 
@param definition Bean定义信息
     * 
@return Bean Class
     * 
@throws BeansException
     
*/

    @SuppressWarnings(
"unchecked")
    
private Class getBeanClassByName(String name, BeanDefinition definition) 
            
throws BeansException {
        
        
try {
            
return Class.forName(definition.getBeanClassName());
        }
 catch (ClassNotFoundException e) {
            
throw new CannotLoadBeanClassException("No class found", name, 
                    definition.getBeanClassName(), e);
        }

    }

}

 

public class DaoA implements IDaoA {

    
private String param;
    
    
public void operationA() {
        System.out.println(
"DaoA.operationA(" + param + ")");
    }


    
public String getParam() {
        
return param;
    }


    
public void setParam(String param) {
        
this.param = param;
    }

}

public class DaoB implements IDaoB {

    
public void operationB() {
        System.out.println(
"DaoB.operationB()");
    }

}

public class Service implements IService {

    
private IDaoA daoA = null;
    
    
private IDaoB daoB = null;
    
    
public void service() {
        System.out.println(
"********service begin ***********");
        daoA.operationA();
        daoB.operationB();
        System.out.println(
"********service end *************");
    }


    
public IDaoA getDaoA() {
        
return daoA;
    }


    @Inject
    
public void setDaoA(IDaoA daoA) {
        
this.daoA = daoA;
    }


    
public IDaoB getDaoB() {
        
return daoB;
    }


    @Inject
    
public void setDaoB(IDaoB daoB) {
        
this.daoB = daoB;
    }

}
(注意set方法)

配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns
="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    
    
<bean id="daoA" class="injection.DaoA">
        
<property name="param">
            
<value>lg</value>
        
</property>
    
</bean>
    
    
<bean id="daoB" class="injection.DaoB"/>
    
<bean id="service" class="injection.Service"/>
    
    
<bean id="injection" class="injection.InjectProcessor"/>
</beans>
ApplicationContext会检测部署在它之上实现了BeanFactoryPostProcessor接口的bean,并在适当的时候会自动调用bean工厂后配置处理器。部署一个后配置处理器同部署其它bean没什么区别。

测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AnnotationInjectTest {

    
public static void main(String[] args) {
        ApplicationContext ac 
= new ClassPathXmlApplicationContext("injection/applicationContext.xml");
        
        IService service 
= (IService) ac.getBean("service");
        service.service();
    }

}

测试结果如下:
********service begin ***********
DaoA.operationA(lg)
DaoB.operationB()
********service end *************

posted on 2008-12-17 01:17 永远的火焰舞者 阅读(550) 评论(0)  编辑  收藏 所属分类: spring


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(1)

随笔分类(10)

随笔档案(9)

文章档案(1)

搜索

最新评论

  • 1. re: JForum安装
  • 我就是想研究下sso,哈哈!再在JForum的基础上二次开发玩玩 呵呵
  • --Jlg
  • 2. re: JForum安装
  • JForum的代码还比较清晰,但谈不上强大,虽然一般也足够用了。
  • --一农

阅读排行榜

评论排行榜