Prior to this change, to specify two or more annotation include/exclude
filters, one would declare @ComponentScan as follows:
@ComponentScan(basePackages="example.scannable",
useDefaultFilters=false,
includeFilters={
@Filter(MyStereotype.class),
@Filter(MyComponent.class)
})
This was because @Filter's 'value' attribute accepted exactly one
argument.
Now, any given @Filter may accept one or more value arguments, allowing
for more concise @ComponentScan declarations:
@ComponentScan(basePackages="example.scannable",
useDefaultFilters=false,
includeFilters=@Filter({MyStereotype.class, MyComponent.class}))
Supplying multiple arguments in this way assumes that they are the same
type of filter, e.g. ANNOTATION, ASSIGNABLE_TYPE, or CUSTOM. To declare
multiple *different* types of filters, multiple @Filter annotations are
still required, e.g.:
@ComponentScan(
includeFilters={
@Filter(type=ANNOTATION, value=MyStereotype.class),
@Filter(type=ASSIGNABLE_TYPE, value={Foo.class, Bar.class})
})
Note that specifying zero arguments, e.g. @Filter({}) is nonsensical; it
will have no effect on component scanning, but does not raise an error.
Issue: SPR-8881
For clarity, add @Target({}) to definition of @Filter, constraining it
to complex annotation composition only; i.e. it cannot be placed on
any element, only within annotations, e.g.
@ComponentScan(includeFilters=@Filter(...))
is legal, while
@Filter
public class MyType { }
is not.
Also, widen @Retention from SOURCE to RUNTIME, even though it is not
technically necessary, as all parsing of @Filter annotations happens via
ASM, i.e. at the source level. This change is made primarily for
consistency (@ComponentScan's Retention is RUNTIME) and in avoidance of
potential confusion or surprise on the part of those casually browsing
the code.
This method allows a view to access the combined context path and
servlet mapping path for prefixing URLs without having to specify
the literal part of a servlet mapping such as "/main/*")
explicitly everywhere. For example:
${requestContext.pathToServlet}/css/main.css