让Spring管理容器外的对象
Spring为管理容器外创建的对象提供了一个AspectJ语法编写的切面类:org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect,它位于spring-aspects.jar包中。spring-aspects.jar类包没有随Spring标准版一起发布,但你可以在完整版中找到它,位于Spring项目的dist目录下。该切面类匹配所有标注@Configurable的类,该注解类org.springframework.beans.factory.annotation.Configurable则位于spring.jar中。
AspectJ在类加载时,将AnnotationBeanConfigurerAspect切面将织入到标注有@Configurable注解的类中。
AnnotationBeanConfigurerAspect将这些类和Spring IoC容器进行了关联,AnnotationBeanConfigurerAspect本身实现了BeanFactoryAware的接口。
这样,标注了@Configurable的类通过AspectJ LTW织入器织入AnnotationBeanConfigurerAspect切面后,就和Spring IoC容器间接关联起来了,实现了Spring管理容器外对象的功能。
展现该功能的一个比较好的实例是管理Spring IoC容器外的领域对象。回想一下我们通常如何进行Dao类的单元测试:比如测试一个论坛主题ThreadDao。首先,我们需要在单元测试类中手工创建论坛主题Thread领域对象、帖子Topic领域对象、附件Attachment领域对象并设置好属性值,然后手工设置这些领域对象的关联关系。
对于习惯了使用Spring IoC依赖注入功能的开发者而言,可能更希望让Spring IoC容器来做这样工作——当然,原来我们就可以做这样的工作,在Spring配置文件中配置好领域对象,然后通过ctx.getBean(beanName)获取领域对象。但很多开发者可能并不喜欢这种方式。他们既希望以传统的new Thread()方式创建领域对象,但又能够享受Spring IoC所提供的依赖注入的好处。Spring管理容器外对象的功能让我们拥有了这个能力。
下面,我们将通过一个实例展现这一神秘的功能。首先,来看一下我们希望管理的两个领域对象:
Thread是论坛主题的领域对象,一个论坛主题对应一个主帖,并拥有多个跟帖,为了简单,这里仅保留主贴对象topic,Topic领域对象类如下所示:package com.baobaotao.configure;
import java.io.Serializable;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable ①
public class Thread implements Serializable...{
private String title;
private Topic topic;
//get/setter
public String toString()...{
return "title:"+title+";\ntopic:"+topic;
}
}
package com.baobaotao.configure;
import java.io.Serializable;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable ①
public class Topic implements Serializable...{
private String title;
private String content;
//get/setter
public String toString()...{
return "title:"+title+";content:"+content;
}
}
