diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java b/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java index 43c26d4de3..a99d95b152 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java +++ b/spring-core/src/main/java/org/springframework/core/convert/support/StringToBooleanConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,9 +30,9 @@ import org.springframework.core.convert.converter.Converter; */ final class StringToBooleanConverter implements Converter { - private static final Set trueValues = new HashSet(4); + private static final Set trueValues = new HashSet(8); - private static final Set falseValues = new HashSet(4); + private static final Set falseValues = new HashSet(8); static { trueValues.add("true"); @@ -46,10 +46,11 @@ final class StringToBooleanConverter implements Converter { falseValues.add("0"); } + @Override public Boolean convert(String source) { String value = source.trim(); - if ("".equals(value)) { + if (value.isEmpty()) { return null; } value = value.toLowerCase(); diff --git a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java index 1559d1d771..23296c7052 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java +++ b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java @@ -715,8 +715,8 @@ public class HttpHeaders implements MultiValueMap, Serializable return; } Assert.notNull(name, "'name' must not be null"); - String encodedFileName = encodeHeaderFieldParam(filename, charset); - set(CONTENT_DISPOSITION, "form-data; name=\"" + name + '\"' + "; filename*=" + encodedFileName); + String encodedFilename = encodeHeaderFieldParam(filename, charset); + set(CONTENT_DISPOSITION, "form-data; name=\"" + name + '\"' + "; filename*=" + encodedFilename); } /** diff --git a/src/asciidoc/core-aop-api.adoc b/src/asciidoc/core-aop-api.adoc index 3f6cf96478..6ca07d00ae 100644 --- a/src/asciidoc/core-aop-api.adoc +++ b/src/asciidoc/core-aop-api.adoc @@ -2,8 +2,11 @@ = Spring AOP APIs + + [[aop-api-introduction]] == Introduction + The previous chapter described the Spring's support for AOP using @AspectJ and schema-based aspect definitions. In this chapter we discuss the lower-level Spring AOP APIs and the AOP support used in Spring 1.2 applications. For new @@ -18,12 +21,14 @@ in Spring 4.0. [[aop-api-pointcuts]] == Pointcut API in Spring + Let's look at how Spring handles the crucial pointcut concept. [[aop-api-concepts]] === Concepts + Spring's pointcut model enables pointcut reuse independent of advice types. It's possible to target different advice using the same pointcut. @@ -88,7 +93,6 @@ In this case, the 3-argument matches method will never be invoked. [TIP] ==== - If possible, try to make pointcuts static, allowing the AOP framework to cache the results of pointcut evaluation when an AOP proxy is created. ==== @@ -97,6 +101,7 @@ results of pointcut evaluation when an AOP proxy is created. [[aop-api-pointcut-ops]] === Operations on pointcuts + Spring supports operations on pointcuts: notably, __union__ and __intersection__. * Union means the methods that either pointcut matches. @@ -111,6 +116,7 @@ Spring supports operations on pointcuts: notably, __union__ and __intersection__ [[aop-api-pointcuts-aspectj]] === AspectJ expression pointcuts + Since 2.0, the most important type of pointcut used by Spring is `org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that uses an AspectJ supplied library to parse an AspectJ pointcut expression string. @@ -121,12 +127,14 @@ See the previous chapter for a discussion of supported AspectJ pointcut primitiv [[aop-api-pointcuts-impls]] === Convenience pointcut implementations + Spring provides several convenient pointcut implementations. Some can be used out of the box; others are intended to be subclassed in application-specific pointcuts. [[aop-api-pointcuts-static]] ==== Static pointcuts + Static pointcuts are based on method and target class, and cannot take into account the method's arguments. Static pointcuts are sufficient - __and best__ - for most usages. It's possible for Spring to evaluate a static pointcut only once, when a method is first @@ -137,14 +145,15 @@ Let's consider some static pointcut implementations included with Spring. [[aop-api-pointcuts-regex]] ===== Regular expression pointcuts + One obvious way to specify static pointcuts is regular expressions. Several AOP frameworks besides Spring make this possible. `org.springframework.aop.support.JdkRegexpMethodPointcut` is a generic regular -expression pointcut, using the regular expression support in JDK 1.4+. +expression pointcut that uses the regular expression support in the JDK. -Using the `JdkRegexpMethodPointcut` class, you can provide a list of pattern Strings. If -any of these is a match, the pointcut will evaluate to true. (So the result is -effectively the union of these pointcuts.) +With the `JdkRegexpMethodPointcut` class, you can provide a list of pattern strings. +If any of these is a match, the pointcut evaluates to `true`. (As a consequence, +the resulting pointcut is effectively the union of the specified patterns.) The usage is shown below: @@ -189,12 +198,14 @@ __RegexpMethodPointcutAdvisor__ can be used with any Advice type. [[aop-api-pointcuts-attribute-driven]] ===== Attribute-driven pointcuts + An important type of static pointcut is a __metadata-driven__ pointcut. This uses the values of metadata attributes: typically, source-level metadata. [[aop-api-pointcuts-dynamic]] ==== Dynamic pointcuts + Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account method __arguments__, as well as static information. This means that they must be evaluated with every method invocation; the result cannot be cached, as arguments will @@ -204,12 +215,14 @@ The main example is the `control flow` pointcut. [[aop-api-pointcuts-cflow]] ===== Control flow pointcuts + Spring control flow pointcuts are conceptually similar to AspectJ __cflow__ pointcuts, although less powerful. (There is currently no way to specify that a pointcut executes below a join point matched by another pointcut.) A control flow pointcut matches the current call stack. For example, it might fire if the join point was invoked by a method in the `com.mycompany.web` package, or by the `SomeCaller` class. Control flow pointcuts are specified using the `org.springframework.aop.support.ControlFlowPointcut` class. + [NOTE] ==== Control flow pointcuts are significantly more expensive to evaluate at runtime than even @@ -221,6 +234,7 @@ pointcuts. [[aop-api-pointcuts-superclasses]] === Pointcut superclasses + Spring provides useful pointcut superclasses to help you to implement your own pointcuts. Because static pointcuts are most useful, you'll probably subclass @@ -246,6 +260,7 @@ You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above. [[aop-api-pointcuts-custom]] === Custom pointcuts + Because pointcuts in Spring AOP are Java classes, rather than language features (as in AspectJ) it's possible to declare custom pointcuts, whether static or dynamic. Custom pointcuts in Spring can be arbitrarily complex. However, using the AspectJ pointcut @@ -262,12 +277,14 @@ for example, "all methods that change instance variables in the target object." [[aop-api-advice]] == Advice API in Spring + Let's now look at how Spring AOP handles advice. [[aop-api-advice-lifecycle]] === Advice lifecycles + Each advice is a Spring bean. An advice instance can be shared across all advised objects, or unique to each advised object. This corresponds to __per-class__ or __per-instance__ advice. @@ -285,12 +302,14 @@ It's possible to use a mix of shared and per-instance advice in the same AOP pro [[aop-api-advice-types]] === Advice types in Spring + Spring provides several advice types out of the box, and is extensible to support arbitrary advice types. Let us look at the basic concepts and standard advice types. [[aop-api-advice-around]] ==== Interception around advice + The most fundamental advice type in Spring is __interception around advice__. Spring is compliant with the AOP Alliance interface for around advice using method @@ -347,6 +366,7 @@ currently define pointcut interfaces. [[aop-api-advice-before]] ==== Before advice + A simpler advice type is a __before advice__. This does not need a `MethodInvocation` object, since it will only be called before entering the method. @@ -395,13 +415,13 @@ An example of a before advice in Spring, which counts all method invocations: [TIP] ==== - Before advice can be used with any pointcut. ==== [[aop-api-advice-throws]] ==== Throws advice + __Throws advice__ is invoked after the return of the join point if the join point threw an exception. Spring offers typed throws advice. Note that this means that the `org.springframework.aop.ThrowsAdvice` interface does not contain any methods: It is a @@ -478,13 +498,13 @@ exception that is incompatible with the target method's signature!__ [TIP] ==== - Throws advice can be used with any pointcut. ==== [[aop-api-advice-after-returning]] ==== After Returning advice + An after returning advice in Spring must implement the __org.springframework.aop.AfterReturningAdvice__ interface, shown below: @@ -527,13 +547,13 @@ thrown up the interceptor chain instead of the return value. [TIP] ==== - After returning advice can be used with any pointcut. ==== [[aop-api-advice-introduction]] ==== Introduction advice + Spring treats introduction advice as a special kind of interception advice. Introduction requires an `IntroductionAdvisor`, and an `IntroductionInterceptor`, @@ -696,6 +716,7 @@ and stateful mixins. [[aop-api-advisor]] == Advisor API in Spring + In Spring, an Advisor is an aspect that contains just a single advice object associated with a pointcut expression. @@ -714,6 +735,7 @@ chain. [[aop-pfb]] == Using the ProxyFactoryBean to create AOP proxies + If you're using the Spring IoC container (an ApplicationContext or BeanFactory) for your business objects - and you should be! - you will want to use one of Spring's AOP FactoryBeans. (Remember that a factory bean introduces a layer of indirection, enabling @@ -733,6 +755,7 @@ options that are preferable if you don't need such control. [[aop-pfb-1]] === Basics + The `ProxyFactoryBean`, like other Spring `FactoryBean` implementations, introduces a level of indirection. If you define a `ProxyFactoryBean` with name `foo`, what objects referencing `foo` see is not the `ProxyFactoryBean` instance itself, but an object @@ -750,6 +773,7 @@ framework), benefiting from all the pluggability provided by Dependency Injectio [[aop-pfb-2]] === JavaBean properties + In common with most `FactoryBean` implementations provided with Spring, the `ProxyFactoryBean` class is itself a JavaBean. Its properties are used to: @@ -803,6 +827,7 @@ to be applied. An example of using this feature can be found in <