Spring4支持使用Groovy DSL來進行Bean定義配置,其相似於XML,不過由於是Groovy DSL,能夠實現任何複雜的語法配置,可是對於配置,咱們須要那麼複雜嗎?本着學習的態度試用了下其Groovy DSL定義Bean,其主要缺點:java
一、DSL語法規則不足,須要其後續維護;git
二、編輯器的代碼補全須要跟進,不然沒有代碼補全,寫這個很痛苦;github
三、出錯提示不友好,排錯難;web
四、當前對於一些配置仍是須要XML的支持,因此還不是100%的純Groovy DSL;spring
五、目前對整個Spring生態支持仍是不夠的,好比Web,須要觀望。express
其優勢就是其本質是Groovy腳本,因此能夠作很是複雜的配置,若是以上問題可以解決,其也是一個不錯的選擇。在Groovy中的話使用這種配置感受不會有什麼問題,可是在純Java開發環境下也是有它,給個人感受是這個功能其目的是去推廣它的groovy。比較懷疑它的動機。mvc
1、對比
對於我來講,沒有哪一個好/壞,只有適用不適用;開發方便不方便。接下來咱們來看一下各類類型的配置吧:app
XML風格配置編輯器
<context:component-scan base-package="com.sishuok.spring4"/> <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"> <property name="validator" ref="validator"/> </bean> <mvc:annotation-driven validator="validator"/> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/> <property name="validationMessageSource" ref="messageSource"/> </bean>
註解風格配置 ide
@Configuration @EnableWebMvc @ComponentScan(basePackages = "com.sishuok.spring4") public class MvcConfiguration extends WebMvcConfigurationSupport { @Override protected Validator getValidator() { LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean(); localValidatorFactoryBean.setProviderClass(HibernateValidator.class); localValidatorFactoryBean.setValidationMessageSource(messageSource()); return localValidatorFactoryBean; } }
Groovy DSL風格配置
import org.hibernate.validator.HibernateValidator import org.springframework.context.support.ReloadableResourceBundleMessageSource import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean beans { xmlns context: "http://www.springframework.org/schema/context" xmlns mvc: "http://www.springframework.org/schema/mvc" context.'component-scan'('base-package': "com,sishuok.spring4") mvc.'annotation-driven'('validator': "validator") validator(LocalValidatorFactoryBean) { providerClass = HibernateValidator.class validationMessageSource = ref("messageSource") } }
由於Spring4 webmvc沒有提供用於Web環境的Groovy DSL實現的WebApplicationContext,因此爲了在web環境使用,單獨寫了一個WebGenricGroovyApplicationContext,能夠到源碼中查找。
能夠看到,它們以前差異不是特別大;以上只提取了部分配置,完整的配置能夠參考個人github: spring4-showcase
對於註解風格的配置,若是在Servlet3容器中使用的話,能夠藉助WebApplicationInitializer實現無配置:
public class AppInitializer implements WebApplicationInitializer { @Override public void onStartup(javax.servlet.ServletContext sc) throws ServletException { // AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); // rootContext.register(AppConfig.class); // sc.addListener(new ContextLoaderListener(rootContext)); //二、springmvc上下文 AnnotationConfigWebApplicationContext springMvcContext = new AnnotationConfigWebApplicationContext(); springMvcContext.register(MvcConfiguration.class); //三、DispatcherServlet DispatcherServlet dispatcherServlet = new DispatcherServlet(springMvcContext); ServletRegistration.Dynamic dynamic = sc.addServlet("dispatcherServlet", dispatcherServlet); dynamic.setLoadOnStartup(1); dynamic.addMapping("/"); //四、CharacterEncodingFilter FilterRegistration filterRegistration = sc.addFilter("characterEncodingFilter", CharacterEncodingFilter.class); filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*"); } }
到底好仍是很差,須要根據本身項目大小等一些因素來衡量。對於Servlet3能夠參考我github的示例: servlet3-showcase
對於Groovy風格配置,若是語法足夠豐富、Spring內部支持完善,且編輯器支持也很是好的話,也是不錯的選擇。
2、Groovy Bean定義
接下來咱們來看下groovy DSL的具體使用吧:
一、安裝環境
<dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>${groovy.version}</version> </dependency>
我使用的groovy版本是2.2.1
二、相關組件類
此處使用Spring Framework官網的hello world,能夠前往 http://projects.spring.io/spring-framework/ 主頁查看
三、Groovy Bean定義配置文件
import com.sishuok.spring4.xml.MessageServiceImpl import com.sishuok.spring4.xml.MessagePrinter beans { messageService(MessageServiceImpl) {//名字(類型) message = "hello" //注入的屬性 } messagePrinter(MessagePrinter, messageService) //名字(類型,構造器參數列表) }
今後處能夠看到 若是僅僅是簡單的Bean定義,確實比XML簡潔。
四、測試
若是不測試環境能夠這樣測試:
public class XmlGroovyBeanDefinitionTest1 { @Test public void test() { ApplicationContext ctx = new GenericGroovyApplicationContext("classpath:spring-config-xml.groovy"); MessagePrinter messagePrinter = (MessagePrinter) ctx.getBean("messagePrinter"); messagePrinter.printMessage(); } }
使用GenericGroovyApplicationContext加載groovy配置文件。
若是想集成到Spring Test中,能夠這樣:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring-config-xml.groovy", loader = GenericGroovyContextLoader.class) public class XmlGroovyBeanDefinitionTest2 { @Autowired private MessagePrinter messagePrinter; @Test public void test() { messagePrinter.printMessage(); } }
此處須要定義咱們本身的bean loader,即從groovy配置文件加載:
public class GenericGroovyContextLoader extends AbstractGenericContextLoader { @Override protected String getResourceSuffix() { throw new UnsupportedOperationException( "GenericGroovyContextLoader does not support the getResourceSuffix() method"); } @Override protected BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context) { return new GroovyBeanDefinitionReader(context); } }
使用GroovyBeanDefinitionReader來加載groovy配置文件。
到此基本的使用就結束了,還算是比較簡潔,可是咱們已經注意到了,在純Java環境作測試仍是比較麻煩的。 好比沒有給咱們寫好相關的測試支撐類。另外你們能夠前往Spring的github看看在groovy中的單元測試:GroovyBeanDefinitionReaderTests.groovy
再看一下咱們使用註解方式呢:
@Component public class MessageServiceImpl implements MessageService { @Autowired @Qualifier("message") private String message; …… }
@Component public class MessagePrinter { private MessageService messageService; @Autowired public MessagePrinter(MessageService messageService) { this.messageService = messageService; } …… }
此處省略無關代碼,須要的話直接去github查看 。 點擊前往
Groovy配置文件:
beans { xmlns context: "http://www.springframework.org/schema/context" //導入命名空間 context.'component-scan'('base-package': "com.sishuok.spring4") { 'exclude-filter'('type': "aspectj", 'expression': "com.sishuok.spring4.xml.*") } message(String, "hello") {} }