Skip to content

Commit 2047f8d

Browse files
committed
Reference documentation for Groovy bean definition DSL
Issue: SPR-15153
1 parent 54da4a8 commit 2047f8d

File tree

2 files changed

+101
-15
lines changed

2 files changed

+101
-15
lines changed

spring-beans-groovy/src/main/java/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -303,7 +303,7 @@ public AbstractBeanDefinition bean(Class<?> type, Object...args) {
303303
Collection constructorArgs = null;
304304
if (!ObjectUtils.isEmpty(args)) {
305305
int index = args.length;
306-
Object lastArg = args[index-1];
306+
Object lastArg = args[index - 1];
307307
if (lastArg instanceof Closure) {
308308
callable = (Closure) lastArg;
309309
index--;
@@ -456,22 +456,22 @@ protected GroovyBeanDefinitionReader invokeBeanDefiningClosure(Closure callable)
456456
* @return the bean definition wrapper
457457
*/
458458
private GroovyBeanDefinitionWrapper invokeBeanDefiningMethod(String beanName, Object[] args) {
459-
boolean hasClosureArgument = args[args.length - 1] instanceof Closure;
459+
boolean hasClosureArgument = (args[args.length - 1] instanceof Closure);
460460
if (args[0] instanceof Class) {
461-
Class<?> beanClass = (args[0] instanceof Class ? (Class<?>) args[0] : args[0].getClass());
461+
Class<?> beanClass = (Class<?>) args[0];
462462
if (args.length >= 1) {
463463
if (hasClosureArgument) {
464-
if (args.length-1 != 1) {
464+
if (args.length - 1 != 1) {
465465
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(
466-
beanName, beanClass, resolveConstructorArguments(args,1,args.length-1));
466+
beanName, beanClass, resolveConstructorArguments(args, 1, args.length - 1));
467467
}
468468
else {
469469
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, beanClass);
470470
}
471471
}
472472
else {
473473
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(
474-
beanName, beanClass, resolveConstructorArguments(args,1,args.length));
474+
beanName, beanClass, resolveConstructorArguments(args, 1, args.length));
475475
}
476476

477477
}
@@ -483,7 +483,7 @@ else if (args[0] instanceof RuntimeBeanReference) {
483483
else if (args[0] instanceof Map) {
484484
// named constructor arguments
485485
if (args.length > 1 && args[1] instanceof Class) {
486-
List constructorArgs = resolveConstructorArguments(args, 2, hasClosureArgument ? args.length-1 : args.length);
486+
List constructorArgs = resolveConstructorArguments(args, 2, hasClosureArgument ? args.length - 1 : args.length);
487487
this.currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, (Class)args[1], constructorArgs);
488488
Map namedArgs = (Map)args[0];
489489
for (Object o : namedArgs.keySet()) {
@@ -519,12 +519,12 @@ else if (args[0] instanceof Closure) {
519519
this.currentBeanDefinition.getBeanDefinition().setAbstract(true);
520520
}
521521
else {
522-
List constructorArgs = resolveConstructorArguments(args, 0, hasClosureArgument ? args.length-1 : args.length);
522+
List constructorArgs = resolveConstructorArguments(args, 0, hasClosureArgument ? args.length - 1 : args.length);
523523
currentBeanDefinition = new GroovyBeanDefinitionWrapper(beanName, null, constructorArgs);
524524
}
525525

526526
if (hasClosureArgument) {
527-
Closure callable = (Closure)args[args.length-1];
527+
Closure callable = (Closure) args[args.length - 1];
528528
callable.setDelegate(this);
529529
callable.setResolveStrategy(Closure.DELEGATE_FIRST);
530530
callable.call(new Object[]{currentBeanDefinition});

src/asciidoc/core-beans.adoc

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
[[beans-introduction]]
66
== Introduction to the Spring IoC container and beans
7+
78
This chapter covers the Spring Framework implementation of the Inversion of Control
89
(IoC) footnote:[See pass:specialcharacters,macros[<<background-ioc>>] ] principle. IoC
910
is also known as __dependency injection__ (DI). It is a process whereby objects define
@@ -44,6 +45,7 @@ among them, are reflected in the __configuration metadata__ used by a container.
4445

4546
[[beans-basics]]
4647
== Container overview
48+
4749
The interface `org.springframework.context.ApplicationContext` represents the Spring IoC
4850
container and is responsible for instantiating, configuring, and assembling the
4951
aforementioned beans. The container gets its instructions on what objects to
@@ -290,6 +292,44 @@ locations, for example, through "${...}" placeholders that are resolved against
290292
system properties at runtime.
291293
====
292294

295+
The import directive is a feature provided by the beans namespace itself. Further
296+
configuration features beyond plain bean definitions are available in a selection
297+
of XML namespaces provided by Spring, e.g. the "context" and the "util" namespace.
298+
299+
300+
[[groovy-bean-definition-dsl]]
301+
==== The Groovy Bean Definition DSL
302+
303+
As a further example for externalized configuration metadata, bean definitions can also
304+
be expressed in Spring's Groovy Bean Definition DSL, as known from the Grails framework.
305+
Typically, such configuration will live in a ".groovy" file with a structure as follows:
306+
307+
[source,java,indent=0]
308+
[subs="verbatim,quotes"]
309+
----
310+
beans {
311+
dataSource(BasicDataSource) {
312+
driverClassName = "org.hsqldb.jdbcDriver"
313+
url = "jdbc:hsqldb:mem:grailsDB"
314+
username = "sa"
315+
password = ""
316+
settings = [mynew:"setting"]
317+
}
318+
sessionFactory(SessionFactory) {
319+
dataSource = dataSource
320+
}
321+
myService(MyService) {
322+
nestedBean = { AnotherBean bean ->
323+
dataSource = dataSource
324+
}
325+
}
326+
}
327+
----
328+
329+
This configuration style is largely equivalent to XML bean definitions and even
330+
supports Spring's XML configuration namespaces. It also allows for importing XML
331+
bean definition files through an "importBeans" directive.
332+
293333

294334

295335
[[beans-factory-client]]
@@ -305,8 +345,7 @@ The `ApplicationContext` enables you to read bean definitions and access them as
305345
[subs="verbatim,quotes"]
306346
----
307347
// create and configure beans
308-
ApplicationContext context =
309-
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
348+
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
310349
311350
// retrieve configured instance
312351
PetStoreService service = context.getBean("petStore", PetStoreService.class);
@@ -315,12 +354,46 @@ The `ApplicationContext` enables you to read bean definitions and access them as
315354
List<String> userList = service.getUsernameList();
316355
----
317356

318-
You use `getBean()` to retrieve instances of your beans. The `ApplicationContext`
357+
With Groovy configuration, bootstrapping looks very similar, just a different context
358+
implementation class which is Groovy-aware (but also understands XML bean definitions):
359+
360+
[source,java,indent=0]
361+
[subs="verbatim,quotes"]
362+
----
363+
ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");
364+
----
365+
366+
The most flexible variant is `GenericApplicationContext` in combination with reader
367+
delegates, e.g. with `XmlBeanDefinitionReader` for XML files:
368+
369+
[source,java,indent=0]
370+
[subs="verbatim,quotes"]
371+
----
372+
GenericApplicationContext context = new GenericApplicationContext();
373+
new XmlBeanDefinitionReader(ctx).loadBeanDefinitions("services.xml", "daos.xml");
374+
context.refresh();
375+
----
376+
377+
Or with `GroovyBeanDefinitionReader` for Groovy files:
378+
379+
[source,java,indent=0]
380+
[subs="verbatim,quotes"]
381+
----
382+
GenericApplicationContext context = new GenericApplicationContext();
383+
new GroovyBeanDefinitionReader(ctx).loadBeanDefinitions("services.groovy", "daos.groovy");
384+
context.refresh();
385+
----
386+
387+
Such reader delegates can be mixed and matched on the same `ApplicationContext`,
388+
reading bean definitions from diverse configuration sources, if desired.
389+
390+
You can then use `getBean` to retrieve instances of your beans. The `ApplicationContext`
319391
interface has a few other methods for retrieving beans, but ideally your application
320392
code should never use them. Indeed, your application code should have no calls to the
321393
`getBean()` method at all, and thus no dependency on Spring APIs at all. For example,
322-
Spring's integration with web frameworks provides for dependency injection for various
323-
web framework classes such as controllers and JSF-managed beans.
394+
Spring's integration with web frameworks provides dependency injection for various web
395+
framework components such as controllers and JSF-managed beans, allowing you to declare
396+
a dependency on a specific bean through metadata (e.g. an autowiring annotation).
324397

325398

326399

@@ -497,6 +570,8 @@ If you are using Java-configuration, the `@Bean` annotation can be used to provi
497570
see <<beans-java-bean-annotation>> for details.
498571
****
499572

573+
574+
500575
[[beans-factory-class]]
501576
=== Instantiating beans
502577

@@ -7100,6 +7175,7 @@ method that returns `true` or `false`. For example, here is the actual
71007175
See the {api-spring-framework}/context/annotation/Conditional.html[
71017176
`@Conditional` javadocs] for more detail.
71027177

7178+
71037179
[[beans-java-combining]]
71047180
==== Combining Java and XML configuration
71057181

@@ -7372,6 +7448,7 @@ certain profile of bean definitions in situation A, and a different profile in
73727448
situation B. Let's first see how we can update our configuration to reflect
73737449
this need.
73747450

7451+
73757452
[[beans-definition-profiles-java]]
73767453
==== @Profile
73777454

@@ -7541,6 +7618,7 @@ The `spring-bean.xsd` has been constrained to allow such elements only as the
75417618
last ones in the file. This should help provide flexibility without incurring
75427619
clutter in the XML files.
75437620

7621+
75447622
[[beans-definition-profiles-enable]]
75457623
==== Activating a profile
75467624

@@ -7587,6 +7665,7 @@ Declaratively, `spring.profiles.active` may accept a comma-separated list of pro
75877665
-Dspring.profiles.active="profile1,profile2"
75887666
----
75897667

7668+
75907669
[[beans-definition-profiles-default]]
75917670
==== Default profile
75927671

@@ -7617,6 +7696,8 @@ profile is enabled, the _default_ profile will not apply.
76177696
The name of the default profile can be changed using `setDefaultProfiles()` on
76187697
the `Environment` or declaratively using the `spring.profiles.default` property.
76197698

7699+
7700+
76207701
[[beans-property-source-abstraction]]
76217702
=== PropertySource abstraction
76227703

@@ -7692,6 +7773,8 @@ any `foo` property in any other `PropertySource`. The
76927773
API exposes a number of methods that allow for precise manipulation of the set of
76937774
property sources.
76947775

7776+
7777+
76957778
=== @PropertySource
76967779

76977780
The {api-spring-framework}/context/annotation/PropertySource.html[`@PropertySource`]
@@ -7749,6 +7832,7 @@ as a default. If no default is specified and a property cannot be resolved, an
77497832
`IllegalArgumentException` will be thrown.
77507833

77517834

7835+
77527836
=== Placeholder resolution in statements
77537837

77547838
Historically, the value of placeholders in elements could be resolved only against
@@ -7771,6 +7855,8 @@ property is defined, as long as it is available in the `Environment`:
77717855
----
77727856

77737857

7858+
7859+
77747860
[[context-load-time-weaver]]
77757861
== Registering a LoadTimeWeaver
77767862

0 commit comments

Comments
 (0)