Skip to content

Commit 6deccf1

Browse files
committed
Reference documentation for Groovy bean definition DSL
Issue: SPR-15153 (cherry picked from commit 2047f8d)
1 parent 391ebc8 commit 6deccf1

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

@@ -7131,6 +7206,7 @@ method that returns `true` or `false`. For example, here is the actual
71317206
See the {api-spring-framework}/context/annotation/Conditional.html[
71327207
`@Conditional` javadocs] for more detail.
71337208

7209+
71347210
[[beans-java-combining]]
71357211
==== Combining Java and XML configuration
71367212

@@ -7403,6 +7479,7 @@ certain profile of bean definitions in situation A, and a different profile in
74037479
situation B. Let's first see how we can update our configuration to reflect
74047480
this need.
74057481

7482+
74067483
[[beans-definition-profiles-java]]
74077484
==== @Profile
74087485

@@ -7572,6 +7649,7 @@ The `spring-bean.xsd` has been constrained to allow such elements only as the
75727649
last ones in the file. This should help provide flexibility without incurring
75737650
clutter in the XML files.
75747651

7652+
75757653
[[beans-definition-profiles-enable]]
75767654
==== Activating a profile
75777655

@@ -7618,6 +7696,7 @@ Declaratively, `spring.profiles.active` may accept a comma-separated list of pro
76187696
-Dspring.profiles.active="profile1,profile2"
76197697
----
76207698

7699+
76217700
[[beans-definition-profiles-default]]
76227701
==== Default profile
76237702

@@ -7648,6 +7727,8 @@ profile is enabled, the _default_ profile will not apply.
76487727
The name of the default profile can be changed using `setDefaultProfiles()` on
76497728
the `Environment` or declaratively using the `spring.profiles.default` property.
76507729

7730+
7731+
76517732
[[beans-property-source-abstraction]]
76527733
=== PropertySource abstraction
76537734

@@ -7725,6 +7806,8 @@ any `foo` property in any other `PropertySource`. The
77257806
API exposes a number of methods that allow for precise manipulation of the set of
77267807
property sources.
77277808

7809+
7810+
77287811
=== @PropertySource
77297812

77307813
The {api-spring-framework}/context/annotation/PropertySource.html[`@PropertySource`]
@@ -7782,6 +7865,7 @@ as a default. If no default is specified and a property cannot be resolved, an
77827865
`IllegalArgumentException` will be thrown.
77837866

77847867

7868+
77857869
=== Placeholder resolution in statements
77867870

77877871
Historically, the value of placeholders in elements could be resolved only against
@@ -7804,6 +7888,8 @@ property is defined, as long as it is available in the `Environment`:
78047888
----
78057889

78067890

7891+
7892+
78077893
[[context-load-time-weaver]]
78087894
== Registering a LoadTimeWeaver
78097895

0 commit comments

Comments
 (0)