Restore annotated code samples

See gh-21778
This commit is contained in:
Sebastien Deleuze 2019-08-14 10:00:03 +02:00
parent ec740559ed
commit db02d38c89
4 changed files with 91 additions and 54 deletions

View File

@ -481,33 +481,38 @@ pointcut expressions by name. The following example shows three pointcut express
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java .Java
---- ----
// matches if a method execution join point represents the execution of any public method
@Pointcut("execution(public * *(..))") @Pointcut("execution(public * *(..))")
private void anyPublicOperation() {} private void anyPublicOperation() {} // <1>
// matches if a method execution is in the trading module
@Pointcut("within(com.xyz.someapp.trading..*)") @Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {} private void inTrading() {} // <2>
// matches if a method execution represents any public method in the trading module
@Pointcut("anyPublicOperation() && inTrading()") @Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {} private void tradingOperation() {} // <3>
---- ----
<1> `anyPublicOperation` matches if a method execution join point represents the execution
of any public method.
<2> `inTrading` matches if a method execution is in the trading module.
<3> `tradingOperation` matches if a method execution represents any public method in the
trading module.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
// matches if a method execution join point represents the execution of any public method.
@Pointcut("execution(public * *(..))") @Pointcut("execution(public * *(..))")
private fun anyPublicOperation() {} private fun anyPublicOperation() {} // <1>
// matches if a method execution is in the trading module
@Pointcut("within(com.xyz.someapp.trading..*)") @Pointcut("within(com.xyz.someapp.trading..*)")
private fun inTrading() {} private fun inTrading() {} // <2>
// matches if a method execution represents any public method in the trading module
@Pointcut("anyPublicOperation() && inTrading()") @Pointcut("anyPublicOperation() && inTrading()")
private fun tradingOperation() {} private fun tradingOperation() {} // <3>
---- ----
<1> `anyPublicOperation` matches if a method execution join point represents the execution
of any public method.
<2> `inTrading` matches if a method execution is in the trading module.
<3> `tradingOperation` matches if a method execution represents any public method in the
trading module.
It is a best practice to build more complex pointcut expressions out of smaller named It is a best practice to build more complex pointcut expressions out of smaller named
components, as shown earlier. When referring to pointcuts by name, normal Java visibility components, as shown earlier. When referring to pointcuts by name, normal Java visibility

View File

@ -860,14 +860,10 @@ we can parse our custom XML content, as you can see in the following example:
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
// We use the Spring-provided AbstractSingleBeanDefinitionParser to handle a lot of public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { // <1>
// the basic grunt work of creating a single BeanDefinition.
public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected Class getBeanClass(Element element) { protected Class getBeanClass(Element element) {
// We supply the AbstractSingleBeanDefinitionParser superclass with the type that our return SimpleDateFormat.class; // <2>
// single BeanDefinition represents.
return SimpleDateFormat.class;
} }
protected void doParse(Element element, BeanDefinitionBuilder bean) { protected void doParse(Element element, BeanDefinitionBuilder bean) {
@ -884,6 +880,11 @@ we can parse our custom XML content, as you can see in the following example:
} }
---- ----
<1> We use the Spring-provided `AbstractSingleBeanDefinitionParser` to handle a lot of
the basic grunt work of creating a single `BeanDefinition`.
<2> We supply the `AbstractSingleBeanDefinitionParser` superclass with the type that our
single `BeanDefinition` represents.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
@ -896,13 +897,9 @@ we can parse our custom XML content, as you can see in the following example:
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
// We use the Spring-provided AbstractSingleBeanDefinitionParser to handle a lot of class SimpleDateFormatBeanDefinitionParser : AbstractSingleBeanDefinitionParser() { // <1>
// the basic grunt work of creating a single BeanDefinition.
class SimpleDateFormatBeanDefinitionParser : AbstractSingleBeanDefinitionParser() {
override fun getBeanClass(element: Element): Class<*>? { override fun getBeanClass(element: Element): Class<*>? { // <2>
// We supply the AbstractSingleBeanDefinitionParser superclass with the type that our
// single BeanDefinition represents.
return SimpleDateFormat::class.java return SimpleDateFormat::class.java
} }
@ -919,6 +916,11 @@ we can parse our custom XML content, as you can see in the following example:
} }
} }
---- ----
<1> We use the Spring-provided `AbstractSingleBeanDefinitionParser` to handle a lot of
the basic grunt work of creating a single `BeanDefinition`.
<2> We supply the `AbstractSingleBeanDefinitionParser` superclass with the type that our
single `BeanDefinition` represents.
In this simple case, this is all that we need to do. The creation of our single In this simple case, this is all that we need to do. The creation of our single
`BeanDefinition` is handled by the `AbstractSingleBeanDefinitionParser` superclass, as `BeanDefinition` is handled by the `AbstractSingleBeanDefinitionParser` superclass, as

View File

@ -5599,24 +5599,27 @@ following example:
public class MovieRecommender { public class MovieRecommender {
@Autowired @Autowired
@Offline @Offline // <1>
private MovieCatalog offlineCatalog; private MovieCatalog offlineCatalog;
// ... // ...
} }
---- ----
<1> This line adds the `@Offline` annotation.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
class MovieRecommender { class MovieRecommender {
@Autowired @Autowired
@Offline @Offline // <1>
private lateinit var offlineCatalog: MovieCatalog private lateinit var offlineCatalog: MovieCatalog
// ... // ...
} }
---- ----
<1> This line adds the `@Offline` annotation.
Now the bean definition only needs a qualifier `type`, as shown in the following example: Now the bean definition only needs a qualifier `type`, as shown in the following example:
@ -5915,21 +5918,24 @@ as demonstrated in the following example:
private MovieFinder movieFinder; private MovieFinder movieFinder;
@Resource(name="myMovieFinder") // This line injects a @Resource @Resource(name="myMovieFinder") // <1>
public void setMovieFinder(MovieFinder movieFinder) { public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder; this.movieFinder = movieFinder;
} }
} }
---- ----
<1> This line injects a `@Resource`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
class SimpleMovieLister { class SimpleMovieLister {
@Resource(name="myMovieFinder") // This line injects a @Resource @Resource(name="myMovieFinder") // <1>
private lateinit var movieFinder:MovieFinder private lateinit var movieFinder:MovieFinder
} }
---- ----
<1> This line injects a `@Resource`.
If no name is explicitly specified, the default name is derived from the field name or If no name is explicitly specified, the default name is derived from the field name or
@ -5986,10 +5992,8 @@ named "customerPreferenceDao" and then falls back to a primary type match for th
@Resource @Resource
private CustomerPreferenceDao customerPreferenceDao; private CustomerPreferenceDao customerPreferenceDao;
// The context field is injected based on the known resolvable dependency
// type: ApplicationContext
@Resource @Resource
private ApplicationContext context; private ApplicationContext context; // <1>
public MovieRecommender() { public MovieRecommender() {
} }
@ -5997,6 +6001,9 @@ named "customerPreferenceDao" and then falls back to a primary type match for th
// ... // ...
} }
---- ----
<1> The `context` field is injected based on the known resolvable dependency type:
`ApplicationContext`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
@ -6005,14 +6012,15 @@ named "customerPreferenceDao" and then falls back to a primary type match for th
@Resource @Resource
private lateinit var customerPreferenceDao: CustomerPreferenceDao private lateinit var customerPreferenceDao: CustomerPreferenceDao
// The context field is injected based on the known resolvable dependency
// type: ApplicationContext
@Resource @Resource
private lateinit var context: ApplicationContext private lateinit var context: ApplicationContext // <1>
// ... // ...
} }
---- ----
<1> The `context` field is injected based on the known resolvable dependency type:
`ApplicationContext`.
[[beans-value-annotations]] [[beans-value-annotations]]
=== Using `@Value` === Using `@Value`
@ -6341,24 +6349,27 @@ is meta-annotated with `@Component`, as the following example shows:
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
@Component // Causes @Service to be treated in the same way as @Component @Component // <1>
public @interface Service { public @interface Service {
// ... // ...
} }
---- ----
<1> The `Component` causes `@Service` to be treated in the same way as `@Component`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
@Target(AnnotationTarget.TYPE) @Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented @MustBeDocumented
@Component // Causes @Service to be treated in the same way as @Component @Component // <1>
annotation class Service { annotation class Service {
// ... // ...
} }
---- ----
<1> The `Component` causes `@Service` to be treated in the same way as `@Component`.
You can also combine meta-annotations to create "`composed annotations`". For example, You can also combine meta-annotations to create "`composed annotations`". For example,
the `@RestController` annotation from Spring MVC is composed of `@Controller` and the `@RestController` annotation from Spring MVC is composed of `@Controller` and
@ -7779,20 +7790,23 @@ To enable component scanning, you can annotate your `@Configuration` class as fo
.Java .Java
---- ----
@Configuration @Configuration
@ComponentScan(basePackages = "com.acme") // This annotation enables component scanning @ComponentScan(basePackages = "com.acme") // <1>
public class AppConfig { public class AppConfig {
... ...
} }
---- ----
<1> This annotation enables component scanning.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
@Configuration @Configuration
@ComponentScan(basePackages = ["com.acme"]) // This annotation enables component scanning @ComponentScan(basePackages = ["com.acme"]) // <1>
class AppConfig { class AppConfig {
// ... // ...
} }
---- ----
<1> This annotation enables component scanning.
[TIP] [TIP]
@ -9655,7 +9669,7 @@ the following example shows:
public class AppConfig { public class AppConfig {
@Bean("dataSource") @Bean("dataSource")
@Profile("development") // The standaloneDataSource method is available only in the development profile @Profile("development") // <1>
public DataSource standaloneDataSource() { public DataSource standaloneDataSource() {
return new EmbeddedDatabaseBuilder() return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL) .setType(EmbeddedDatabaseType.HSQL)
@ -9665,13 +9679,16 @@ the following example shows:
} }
@Bean("dataSource") @Bean("dataSource")
@Profile("production") // The jndiDataSource method is available only in the production profile @Profile("production") // <2>
public DataSource jndiDataSource() throws Exception { public DataSource jndiDataSource() throws Exception {
Context ctx = new InitialContext(); Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
} }
} }
---- ----
<1> The `standaloneDataSource` method is available only in the `development` profile.
<2> The `jndiDataSource` method is available only in the `production` profile.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
@ -9679,7 +9696,7 @@ the following example shows:
class AppConfig { class AppConfig {
@Bean("dataSource") @Bean("dataSource")
@Profile("development") // The standaloneDataSource method is available only in the development profile @Profile("development") // <1>
fun standaloneDataSource(): DataSource { fun standaloneDataSource(): DataSource {
return EmbeddedDatabaseBuilder() return EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL) .setType(EmbeddedDatabaseType.HSQL)
@ -9689,11 +9706,13 @@ the following example shows:
} }
@Bean("dataSource") @Bean("dataSource")
@Profile("production") // The jndiDataSource method is available only in the production profile @Profile("production") // <2>
fun jndiDataSource() = fun jndiDataSource() =
InitialContext().lookup("java:comp/env/jdbc/datasource") as DataSource InitialContext().lookup("java:comp/env/jdbc/datasource") as DataSource
} }
---- ----
<1> The `standaloneDataSource` method is available only in the `development` profile.
<2> The `jndiDataSource` method is available only in the `production` profile.
[NOTE] [NOTE]
==== ====

View File

@ -69,16 +69,19 @@ The following code introduces the SpEL API to evaluate the literal string expres
.Java .Java
---- ----
ExpressionParser parser = new SpelExpressionParser(); ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'"); // The value of the message variable is 'Hello World' Expression exp = parser.parseExpression("'Hello World'"); // <1>
String message = (String) exp.getValue(); String message = (String) exp.getValue();
---- ----
<1> The value of the message variable is `'Hello World'`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
val parser = SpelExpressionParser() val parser = SpelExpressionParser()
val exp = parser.parseExpression("'Hello World'") // The value of the message variable is 'Hello World' val exp = parser.parseExpression("'Hello World'") // <1>
val message = exp.value as String val message = exp.value as String
---- ----
<1> The value of the message variable is `'Hello World'`.
The SpEL classes and interfaces you are most likely to use are located in the The SpEL classes and interfaces you are most likely to use are located in the
@ -100,18 +103,19 @@ In the following example of method invocation, we call the `concat` method on th
.Java .Java
---- ----
ExpressionParser parser = new SpelExpressionParser(); ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'.concat('!')"); Expression exp = parser.parseExpression("'Hello World'.concat('!')"); // <1>
// The value of message is now 'Hello World!'
String message = (String) exp.getValue(); String message = (String) exp.getValue();
---- ----
<1> The value of `message` is now 'Hello World!'.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
val parser = SpelExpressionParser() val parser = SpelExpressionParser()
val exp = parser.parseExpression("'Hello World'.concat('!')") val exp = parser.parseExpression("'Hello World'.concat('!')") // <1>
// The value of message is now 'Hello World!'
val message = exp.value as String val message = exp.value as String
---- ----
<1> The value of `message` is now 'Hello World!'.
The following example of calling a JavaBean property calls the `String` property `Bytes`: The following example of calling a JavaBean property calls the `String` property `Bytes`:
@ -121,18 +125,21 @@ The following example of calling a JavaBean property calls the `String` property
ExpressionParser parser = new SpelExpressionParser(); ExpressionParser parser = new SpelExpressionParser();
// invokes 'getBytes()' // invokes 'getBytes()'
Expression exp = parser.parseExpression("'Hello World'.bytes"); // This line converts the literal to a byte array Expression exp = parser.parseExpression("'Hello World'.bytes"); // <1>
byte[] bytes = (byte[]) exp.getValue(); byte[] bytes = (byte[]) exp.getValue();
---- ----
<1> This line converts the literal to a byte array.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
val parser = SpelExpressionParser() val parser = SpelExpressionParser()
// invokes 'getBytes()' // invokes 'getBytes()'
val exp = parser.parseExpression("'Hello World'.bytes") // This line converts the literal to a byte array val exp = parser.parseExpression("'Hello World'.bytes") // <1>
val bytes = exp.value as ByteArray val bytes = exp.value as ByteArray
---- ----
<1> This line converts the literal to a byte array.
SpEL also supports nested properties by using the standard dot notation (such as SpEL also supports nested properties by using the standard dot notation (such as
`prop1.prop2.prop3`) and also the corresponding setting of property values. `prop1.prop2.prop3`) and also the corresponding setting of property values.
@ -146,18 +153,21 @@ The following example shows how to use dot notation to get the length of a liter
ExpressionParser parser = new SpelExpressionParser(); ExpressionParser parser = new SpelExpressionParser();
// invokes 'getBytes().length' // invokes 'getBytes().length'
Expression exp = parser.parseExpression("'Hello World'.bytes.length"); // 'Hello World'.bytes.length gives the length of the literal. Expression exp = parser.parseExpression("'Hello World'.bytes.length"); // <1>
int length = (Integer) exp.getValue(); int length = (Integer) exp.getValue();
---- ----
<1> `'Hello World'.bytes.length` gives the length of the literal.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
val parser = SpelExpressionParser() val parser = SpelExpressionParser()
// invokes 'getBytes().length' // invokes 'getBytes().length'
val exp = parser.parseExpression("'Hello World'.bytes.length") // 'Hello World'.bytes.length gives the length of the literal. val exp = parser.parseExpression("'Hello World'.bytes.length") // <1>
val length = exp.value as Int val length = exp.value as Int
---- ----
<1> `'Hello World'.bytes.length` gives the length of the literal.
The String's constructor can be called instead of using a string literal, as the following The String's constructor can be called instead of using a string literal, as the following
example shows: example shows:
@ -166,18 +176,19 @@ example shows:
.Java .Java
---- ----
ExpressionParser parser = new SpelExpressionParser(); ExpressionParser parser = new SpelExpressionParser();
// Construct a new String from the literal and make it be upper case
Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); Expression exp = parser.parseExpression("new String('hello world').toUpperCase()");
String message = exp.getValue(String.class); String message = exp.getValue(String.class);
---- ----
<1> Construct a new `String` from the literal and make it be upper case.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
val parser = SpelExpressionParser() val parser = SpelExpressionParser()
// Construct a new String from the literal and make it be upper case
val exp = parser.parseExpression("new String('hello world').toUpperCase()") val exp = parser.parseExpression("new String('hello world').toUpperCase()")
val message = exp.getValue(String::class.java) val message = exp.getValue(String::class.java)
---- ----
<1> Construct a new `String` from the literal and make it be upper case.
Note the use of the generic method: `public <T> T getValue(Class<T> desiredResultType)`. Note the use of the generic method: `public <T> T getValue(Class<T> desiredResultType)`.