【IT168评论】
在最近的Blog中,Rod Johnson介绍了Spring应用程序的一个新的配置选项,这个新的配置选项并不是打算来取代Spring的基于XML的配置.新的选项在Java类中定义了配置,这个配置Rod Johnson描述为一个小的配置DSL.
值得提到的一点就是,人们经常忽略Spring配置不需要在XML文件中,虽然XML的形式是目前最通用的使用形式.Spring在BeanDefinition接口和子接口的形式上有自己的内部的元数据形式. 代表IOC容器实例的BeanFactory 和ApplicationContext的实现被这种Java元数据赋有强大的动力.并且从元数据的解析中各自分离,这通常是由BeanDefinitionReader实现来执行的.
BeanDefinition最初并不是按开发者的观点来设计的,Spring2.0, NamespaceHandlers(处理XML扩展命名空间的类)产生BeanDefinition元数据,我们引进BeanDefinition,用方便的API使得这更加容易.但是产生BeanDefinition元数据只不过留在架构代码的领域,而不是像你每天写业务逻辑代码和定义规则的Spring bean所做的那样.
今天,我想要描述一个新的选项来在Java代码中定义beans,当前是Spring core增加的扩展功能.
首先来看一个例子:
@Configuration注释标识这个对象作为一个特殊配置类,每一个@Bean方法定义了一个bean.bean的名字是方法的名字,它也可以用注释来定义而外的名字.但是最好从方法中选择名字,而不是注释中,这就像编译器能够确保其唯一性一样.
@Configuration

public class MyConfig ...{
@Bean

public Person rod() ...{
return new Person("Rod Johnson");
}
@Bean(scope = Scope.PROTOTYPE)

public Book book() ...{
Book book = new Book("Expert One-on-One J2EE Design and Development");
book.setAuthor(rod()); // rod() method is actually a bean reference !
return book;
}
}
Beans在Java代码中配置,使用构造器,属性或者任意的方法调用,我们注意到调用另外一个bean方法建立了一个从”book” bean到”rod” bean的依赖.但是在Java的实例对象中没有框架的支持有一个主要的优点:例如:
每个@Bean是Spring组件并能利用所有的Spring服务,例如声明事务管理.
每个public @Bean方法被增加到Spring容器中,因此注入到其他对象,JMX导出和其他定义中是可以的.
在现存的Spring环境中是适合的.
通过比较XML定义来完成同样的结果是更容易的,就象下面这样:
虽然这是基于Java注释的,Java配置机制在注释的使用上是唯一的,注释并没有包含在核心的业务逻辑中,而是在每个独立的配置类中.对配置来说,这是DSL,因此,它保留了Spring的非侵入允诺.,你可以不必改变Java代码来使用.
<bean id="rod" class="Person" scope="singleton">
<constructor-arg>Rod Johnson</constructor-arg>
</bean>
<bean id="book" class="Book" scope="prototype">
<constructor-arg>Expert One-on-One J2EE Design and Development</constructor-arg>
<property name="author" ref="rod"/>
</bean>
这个配置类,类似与一个XML bean定义文件,并且这样的@Configuration注释包含一些对<bean>元素相似的选项,像默认的延迟初始化,例如:
@Bean注释允许像范围,延迟初始化选项在本地设置,正如<bean>元素,默认的范围是Singleton.
@Configuration(defaultAutowire = Autowire.BY_TYPE, defaultLazy = Lazy.FALSE)

public class DataSourceConfiguration extends ConfigurationSupport ...{
}
【IT168技术文档】
Java配置的样式有些有意思的特点,例如:
参考(例如在例子中”rod” bean的参考)避免重构,任何好的IDE都提供了工具支持.
因为配置是Java类.他们可以参与到继承关系,例如,你可以定义需要一些抽象的@Bean在超类中执行的超类.
创建了一个新的可视选项,@Bean方法被声明为保护类型,这中情况可以从Spring组件的一般特性中得到益处,在外部并不可见.也就是说它是不可注入的也不能通过在IOC Context中调用getBean()方法来获得.
作为Spring XML格式的替代品并不是有意的,像Spring 2.0扩展命名空间,自从Spring1.0属性文件的使用也成为可能.复杂的应用要求配置类型的多样化,Spring的目的在于提供对配置的更好的解决方案.我们继续探讨配置的其他形式.
一般我们将Java和XML配置混合使用,你可以在同样的应用上下文中使用多个Java配置类.
接下来的例子我们使用XML bean定义来定义MyConfig bean,就像上面说的那样能够像其他普通的bean一样可以注入. ConfigurationPostProcessor使用@Configuration注释来出来所有的beans,产生必要的bean定义.
当然,我们可以使用普通bean定义,像这个例子中的SomeRandomBean,你可以构建Java配置和现存XML配置的应用上下文.<beans>
<bean class="..MyConfig"/>
<bean class="org.springframework.beans.factory.java.ConfigurationPostProcessor"/>
![]()
<bean class="SomeRandomBean">
<property…
</bean>
</beans>
使用通配符来从环境变量中加载类,像这样:
类通过使用(并不加载)ASM来检查,在将来的版本中可能会提供自动检测设定.ApplicationContext oneConfig = new
AnnotationApplicationContext(SimpleConfiguration.class.getName());ApplicationContext aBunchOfConfigs = new
AnnotationApplicationContext("**/configuration/*Configuration.class");
该实现并不需要对Spring Core进行任何的修改,IOC容器非常灵活,它将配置对象看作一个factory bean并且每个bean定义那个对象的一个实例工厂方法来支持.这种机制从Spring 1.1就可用,在配置实例上没有一点字节码处理,目前使用CGLIB来确保对singleton范围@Bean方法的重复调用总是返回同样的对象.