Spring Configured Object Broker
我把 Spring 配置的对象叫作 SpringConfigured 对象。创建新的 SpringConfigured 对象之后的需求就是,应当请求 Spring 来配置它。Spring ApplicationContext 支持的 SpringConfiguredObjectBroker 应当做这项工作,如清单 3 所示:
清单 3. @SpringConfigured 对象代理
public aspect SpringConfiguredObjectBroker
implements ApplicationContextAware {
private ConfigurableListableBeanFactory beanFactory;
/**
* This broker is itself configured by Spring DI, which will
* pass it a reference to the ApplicationContext
*/
public void setApplicationContext(ApplicationContext aContext) {
if (!(aContext instanceof ConfigurableApplicationContext)) {
throw new SpringConfiguredObjectBrokerException(
"ApplicationContext [" + aContext +
"] does not implement ConfigurableApplicationContext"
);
}
this.beanFactory =
((ConfigurableApplicationContext)aContext).getBeanFactory();
}
/**
* creation of any object that we want to be configured by Spring
*/
pointcut springConfiguredObjectCreation(
Object newInstance,
SpringConfigured scAnnotation
)
: initialization((@SpringConfigured *).new(..)) &&
this(newInstance) &&
@this(scAnnotation);
/**
* ask Spring to configure the newly created instance
*/
after(Object newInstance, SpringConfigured scAnn) returning
: springConfiguredObjectCreation(newInstance,scAnn)
{
String beanName = getBeanName(newInstance, scAnn);
beanFactory.applyBeanPropertyValues(newInstance,beanName);
}
/**
* Determine the bean name to use - if one was provided in
* the annotation then use that, otherwise use the class name.
*/
private String getBeanName(Object obj, SpringConfigured ann) {
String beanName = ann.value();
if (beanName.equals(“”)) {
beanName = obj.getClass().getName();
}
return beanName;
}
}
Spring Configured Object Broker 内部
我将依次分析 SpringConfiguredObjectBroker 方面的各个部分。首先,这个方面实现了 Spring 的 ApplicationContextAware 接口。代理方面本身是由 Spring 配置的(这是它得到对应用程序上下文的引用的方式)。让方面实现 ApplicationContextAware 接口,确保了 Spring 知道在配置期间向它传递一个到当前 ApplicationContext 的引用。
切点 springConfiguredObjectCreation() 用 @SpringConfigured 标注与任何对象的初始化连接点匹配。标注和新创建的实例,都在连接点上作为上下文被捕捉到。最后,返回的 after 建议要求 Spring 配置新创建的实例。bean 名称被用来查询实例的配置信息。我可以以 @SpringConfigured 标注的值的形式提供名称,或者也可以默认使用类的名称。
方面的实现本身可以是标准库的一部分(实际上 Spring 的未来发行版会提供这样的方面),在这种情况下,我需要做的全部工作只是对 Spring 要配置的实例的类型进行标注,如下所示:
@SpringConfigured("AccountBean")
public class Account {
...
}
可以在程序的控制下,创建这一类类型的实例(例如,作为数据库查询的结果),而且它们会把 Spring 为它们配置的全部依赖项自动管理起来。请参阅 下载 得到这里使用的 @SpringConfigured 标注的示例。请注意,当我选择为这个示例使用的标注时(因为提供 bean 名称是非常自然的方式),标记器接口使得在 Java? 1.4 及以下版本上可以使用这种方法。
就像我在这一节开始时讨论的,SpringConfigured 技术不仅仅适用于域实例,而且适用于在 Spring 容器的控制之外创建的任何对象(对于 Spring 本身创建的对象,不需要添加任何复杂性)。通过这种方式,可以配置任何方面,而不用管它的生命周期。例如,如果定义 percflow 方面,那么每次进入相关的控制流程时,AspectJ 都会创建新的方面实例,而 Spring 会在每个方面创建的时候对其进行配置。
