提交 f480333d 编写于 作者: C Chris Beams

Merge 3.1.0 development branch into trunk

Branch in question is 'env' branch from git://git.springsource.org/sandbox/cbeams.git; merged into
git-svn repository with:

    git merge -s recursive -Xtheirs --no-commit env

No merge conflicts, but did need to

    git rm spring-build

prior to committing.

With this change, Spring 3.1.0 development is now happening on SVN
trunk. Further commits to the 3.0.x line will happen in an as-yet
uncreated SVN branch.  3.1.0 snapshots will be available
per the usual nightly CI build from trunk.
上级 b0ea2b13
target
integration-repo
ivy-cache
spring-build
jmx.log
.springBeans
.DS_Store
*.sw*
org.springframework.test/test-output/
build.sh
org.springframework.beans/.settings/org.springframework.ide.eclipse.beans.core.prefs
org.springframework.beans/.settings/org.springframework.ide.eclipse.core.prefs
version=3.0.5
version=3.1.0
# osgi ranges
spring.osgi.range.nq=${version:[=.=.=, =.=.+1)}
spring.osgi.range="${spring.osgi.range.nq}"
......
#Wed Jul 15 00:01:31 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
......
......@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<packaging>jar</packaging>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
......
http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsd
http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-3.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop-3.1.xsd
http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-3.1.xsd
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/aop"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/aop"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.1.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the configuration elements for the Spring Framework's AOP support.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="config">
<xsd:annotation>
<xsd:documentation><![CDATA[
A section (compartmentalization) of AOP-specific configuration (including
aspects, pointcuts, etc).
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="pointcut" type="pointcutType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
A named pointcut definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="advisor" type="advisorType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.aop.Advisor"><![CDATA[
A named advisor definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="aspect" type="aspectType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
A named aspect definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicate that the proxy should be exposed by the AOP framework as a
ThreadLocal for retrieval via the AopContext class. Off by default,
i.e. no guarantees that AopContext access will work.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="aspectj-autoproxy">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"><![CDATA[
Enables the use of the @AspectJ style of Spring AOP.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="include" type="includeType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates that only @AspectJ beans with names matched by the (regex)
pattern will be considered as defining aspects to use for Spring autoproxying.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicate that the proxy should be exposed by the AOP framework as a
ThreadLocal for retrieval via the AopContext class. Off by default,
i.e. no guarantees that AopContext access will work.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="scoped-proxy">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:org.springframework.aop.scope.ScopedProxyFactoryBean"><![CDATA[
Marks a bean definition as being a scoped proxy.
A bean marked as such will be exposed via a proxy, with the 'real'
bean instance being retrieved from some other source (such as a
HttpSession) as and when required.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? This is the default; in order to
switch to standard Java interface-based proxies, turn this flag to "false".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="aspectType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="pointcut" type="pointcutType">
<xsd:annotation>
<xsd:documentation><![CDATA[
A named pointcut definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="declare-parents" type="declareParentsType">
<xsd:annotation>
<xsd:documentation><![CDATA[
Allows this aspect to introduce additional interfaces that the advised
object will transparently implement.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="before" type="basicAdviceType">
<xsd:annotation>
<xsd:documentation><![CDATA[
A before advice definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="after" type="basicAdviceType">
<xsd:annotation>
<xsd:documentation><![CDATA[
An after advice definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="after-returning" type="afterReturningAdviceType">
<xsd:annotation>
<xsd:documentation><![CDATA[
An after-returning advice definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="after-throwing" type="afterThrowingAdviceType">
<xsd:annotation>
<xsd:documentation><![CDATA[
An after-throwing advice definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="around" type="basicAdviceType">
<xsd:annotation>
<xsd:documentation><![CDATA[
An around advice definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
<xsd:attribute name="id" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The unique identifier for an aspect.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the (backing) bean that encapsulates the aspect.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of this aspect when multiple
advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="includeType">
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:java.util.regex.Pattern"><![CDATA[
The regular expression defining which beans are to be included in the
list of @AspectJ beans; beans with names matched by the pattern will
be included.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="pointcutType">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="org.springframework.aop.Pointcut"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The unique identifier for a pointcut.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expression" use="required" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The pointcut expression.
For example : 'execution(* com.xyz.myapp.service.*.*(..))'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="declareParentsType">
<xsd:attribute name="types-matching" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.aop.aspectj.TypePatternClassFilter"><![CDATA[
The AspectJ type expression that defines what types (classes) the
introduction is restricted to.
An example would be 'org.springframework.beans.ITestBean+'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="implement-interface" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The fully qualified name of the interface that will be introduced.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="default-impl" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The fully qualified name of the class that will be instantiated to serve
as the default implementation of the introduced interface.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="delegate-ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to the bean that will serve
as the default implementation of the introduced interface.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="basicAdviceType">
<xsd:attribute name="pointcut" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The associated pointcut expression.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pointcut-ref" type="pointcutRefType">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of an associated pointcut definition.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.aop.Pointcut"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="method" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the method that defines the logic of the advice.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="arg-names" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The comma-delimited list of advice method argument (parameter) names
that will be matched from pointcut parameters.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="afterReturningAdviceType">
<xsd:complexContent>
<xsd:extension base="basicAdviceType">
<xsd:attribute name="returning" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the method parameter to which the return value must
be passed.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="afterThrowingAdviceType">
<xsd:complexContent>
<xsd:extension base="basicAdviceType">
<xsd:attribute name="throwing" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the method parameter to which the thrown exception must
be passed.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="advisorType">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="org.springframework.aop.Advisor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="advice-ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to an advice bean.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.aopalliance.aop.Advice"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pointcut" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
A pointcut expression.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pointcut-ref" type="pointcutRefType">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to a pointcut definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of this advice when multiple
advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:simpleType name="pointcutRefType">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.aop.Pointcut"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string"/>
</xsd:simpleType>
</xsd:schema>
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
......
......@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-asm</artifactId>
<packaging>jar</packaging>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
</parent>
......
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.source=1.5
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<packaging>jar</packaging>
<version>3.0.5.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.5.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<!-- commons logging dependency is in spring-core -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<packaging>jar</packaging>
<version>3.1.0.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.1.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<!-- common logging dependency is in spring-core -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
......@@ -12,6 +12,7 @@
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.6.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.hamcrest/com.springsource.org.hamcrest/1.1.0/com.springsource.org.hamcrest-1.1.0.jar" sourcepath="/IVY_CACHE/org.hamcrest/com.springsource.org.hamcrest/1.1.0/com.springsource.org.hamcrest-sources-1.1.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
#Wed Jul 15 00:01:31 PDT 2009
#Mon Sep 06 21:54:17 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
......
......@@ -17,6 +17,7 @@
<orderEntry type="library" name="EasyMock" level="project" />
<orderEntry type="library" name="javax.el" level="project" />
<orderEntry type="library" name="javax.inject" level="project" />
<orderEntry type="library" name="Hamcrest" level="project" />
<orderEntry type="library" name="JUnit" level="project" />
<orderEntry type="library" name="Log4j" level="project" />
</component>
......
......@@ -31,6 +31,7 @@
<!-- test dependencies -->
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
<dependency org="org.hamcrest" name="com.springsource.org.hamcrest" rev="1.1.0" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="compile->compile"/>
</dependencies>
......
......@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<packaging>jar</packaging>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
......
......@@ -87,6 +87,7 @@ import org.springframework.beans.BeansException;
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Chris Beams
* @since 13 April 2001
* @see BeanNameAware#setBeanName
* @see BeanClassLoaderAware#setBeanClassLoader
......@@ -113,7 +114,6 @@ public interface BeanFactory {
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>This method allows a Spring BeanFactory to be used as a replacement for the
......@@ -240,7 +240,7 @@ public interface BeanFactory {
* @see #getBean
* @see #getType
*/
boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
/**
* Determine the type of the bean with the given name. More specifically,
......
......@@ -110,7 +110,7 @@ public interface ListableBeanFactory extends BeanFactory {
* @see FactoryBean#getObjectType
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class)
*/
String[] getBeanNamesForType(Class type);
String[] getBeanNamesForType(Class<?> type);
/**
* Return the names of beans matching the given type (including subclasses),
......@@ -123,7 +123,7 @@ public interface ListableBeanFactory extends BeanFactory {
* FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
* type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
* (which doesn't require initialization of each FactoryBean).
$ * <p>Does not consider any hierarchy this factory may participate in.
* <p>Does not consider any hierarchy this factory may participate in.
* Use BeanFactoryUtils' <code>beanNamesForTypeIncludingAncestors</code>
* to include beans in ancestor factories too.
* <p>Note: Does <i>not</i> ignore singleton beans that have been registered
......@@ -143,7 +143,7 @@ $ * <p>Does not consider any hierarchy this factory may participate in.
* @see FactoryBean#getObjectType
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)
*/
String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit);
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
/**
* Return the bean instances that match the given object type (including
......
......@@ -432,6 +432,7 @@ public class SingletonBeanFactoryLocator implements BeanFactoryLocator {
protected BeanFactory createDefinition(String resourceLocation, String factoryKey) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
// TODO SPR-7508: consider whether to allow for setEnvironment() here (where would it come from?)
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {
......
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.config;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
import org.springframework.util.StringValueResolver;
/**
* TODO SPR-7508: document.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
*/
public abstract class AbstractPropertyPlaceholderConfigurer extends PropertyResourceConfigurer
implements BeanNameAware, BeanFactoryAware {
/** Default placeholder prefix: "${" */
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
/** Default placeholder suffix: "}" */
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
/** Default value separator: ":" */
public static final String DEFAULT_VALUE_SEPARATOR = ":";
protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;
protected boolean ignoreUnresolvablePlaceholders = false;
private String nullValue;
private String beanName;
private BeanFactory beanFactory;
protected abstract PlaceholderResolver getPlaceholderResolver(Properties props);
/**
* Set the prefix that a placeholder string starts with.
* The default is "${".
* @see #DEFAULT_PLACEHOLDER_PREFIX
*/
public void setPlaceholderPrefix(String placeholderPrefix) {
this.placeholderPrefix = placeholderPrefix;
}
/**
* Set the suffix that a placeholder string ends with.
* The default is "}".
* @see #DEFAULT_PLACEHOLDER_SUFFIX
*/
public void setPlaceholderSuffix(String placeholderSuffix) {
this.placeholderSuffix = placeholderSuffix;
}
/**
* Specify the separating character between the placeholder variable
* and the associated default value, or <code>null</code> if no such
* special character should be processed as a value separator.
* The default is ":".
*/
public void setValueSeparator(String valueSeparator) {
this.valueSeparator = valueSeparator;
}
/**
* Set a value that should be treated as <code>null</code> when
* resolved as a placeholder value: e.g. "" (empty String) or "null".
* <p>Note that this will only apply to full property values,
* not to parts of concatenated values.
* <p>By default, no such null value is defined. This means that
* there is no way to express <code>null</code> as a property
* value unless you explictly map a corresponding value here.
*/
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
/**
* Set whether to ignore unresolvable placeholders.
* <p>Default is "false": An exception will be thrown if a placeholder fails
* to resolve. Switch this flag to "true" in order to preserve the placeholder
* String as-is in such a case, leaving it up to other placeholder configurers
* to resolve it.
*/
public void setIgnoreUnresolvablePlaceholders(boolean ignoreUnresolvablePlaceholders) {
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
}
/**
* Only necessary to check that we're not parsing our own bean definition,
* to avoid failing on unresolvable placeholders in properties file locations.
* The latter case can happen with placeholders for system properties in
* resource locations.
* @see #setLocations
* @see org.springframework.core.io.ResourceEditor
*/
public void setBeanName(String beanName) {
this.beanName = beanName;
}
/**
* Only necessary to check that we're not parsing our own bean definition,
* to avoid failing on unresolvable placeholders in properties file locations.
* The latter case can happen with placeholders for system properties in
* resource locations.
* @see #setLocations
* @see org.springframework.core.io.ResourceEditor
*/
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
for (String curName : beanNames) {
// Check that we're not parsing our own bean definition,
// to avoid failing on unresolvable placeholders in properties file locations.
if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
try {
visitor.visitBeanDefinition(bd);
}
catch (Exception ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage());
}
}
}
// New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
beanFactoryToProcess.resolveAliases(valueResolver);
// New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}
private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
private final PropertyPlaceholderHelper helper;
private final PlaceholderResolver resolver;
public PlaceholderResolvingStringValueResolver(Properties props) {
this.helper = new PropertyPlaceholderHelper(
placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
this.resolver = getPlaceholderResolver(props);
}
public String resolveStringValue(String strVal) throws BeansException {
String value = this.helper.replacePlaceholders(strVal, this.resolver);
return (value.equals(nullValue) ? null : value);
}
}
}
......@@ -173,7 +173,7 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
* @param requiredType type of the property
* @param propertyEditorClass the {@link PropertyEditor} class to register
*/
void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass);
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
/**
* Initialize the given PropertyEditorRegistry with the custom editors
......
......@@ -44,7 +44,7 @@ public interface ConfigurableListableBeanFactory
* for example, String. Default is none.
* @param type the dependency type to ignore
*/
void ignoreDependencyType(Class type);
void ignoreDependencyType(Class<?> type);
/**
* Ignore the given dependency interface for autowiring.
......@@ -57,7 +57,7 @@ public interface ConfigurableListableBeanFactory
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.context.ApplicationContextAware
*/
void ignoreDependencyInterface(Class ifc);
void ignoreDependencyInterface(Class<?> ifc);
/**
* Register a special dependency type with corresponding autowired value.
......@@ -75,7 +75,7 @@ public interface ConfigurableListableBeanFactory
* implementation of the {@link org.springframework.beans.factory.ObjectFactory}
* interface, which allows for lazy resolution of the actual target value.
*/
void registerResolvableDependency(Class dependencyType, Object autowiredValue);
void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue);
/**
* Determine whether the specified bean qualifies as an autowire candidate,
......
......@@ -19,15 +19,12 @@ package org.springframework.beans.factory.config;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.core.Constants;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
import org.springframework.util.StringValueResolver;
/**
* A property resource configurer that resolves placeholders in bean property values of
......@@ -81,6 +78,7 @@ import org.springframework.util.StringValueResolver;
* be detected and decrypted accordingly before processing them.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 02.10.2003
* @see #setLocations
* @see #setProperties
......@@ -91,19 +89,9 @@ import org.springframework.util.StringValueResolver;
* @see #convertPropertyValue
* @see PropertyOverrideConfigurer
*/
public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
public class PropertyPlaceholderConfigurer extends AbstractPropertyPlaceholderConfigurer
implements BeanNameAware, BeanFactoryAware {
/** Default placeholder prefix: "${" */
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
/** Default placeholder suffix: "}" */
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
/** Default value separator: ":" */
public static final String DEFAULT_VALUE_SEPARATOR = ":";
/** Never check system properties. */
public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
......@@ -122,52 +110,10 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
private static final Constants constants = new Constants(PropertyPlaceholderConfigurer.class);
private String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
private String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
private String valueSeparator = DEFAULT_VALUE_SEPARATOR;
private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
private boolean searchSystemEnvironment = true;
private boolean ignoreUnresolvablePlaceholders = false;
private String nullValue;
private String beanName;
private BeanFactory beanFactory;
/**
* Set the prefix that a placeholder string starts with.
* The default is "${".
* @see #DEFAULT_PLACEHOLDER_PREFIX
*/
public void setPlaceholderPrefix(String placeholderPrefix) {
this.placeholderPrefix = placeholderPrefix;
}
/**
* Set the suffix that a placeholder string ends with.
* The default is "}".
* @see #DEFAULT_PLACEHOLDER_SUFFIX
*/
public void setPlaceholderSuffix(String placeholderSuffix) {
this.placeholderSuffix = placeholderSuffix;
}
/**
* Specify the separating character between the placeholder variable
* and the associated default value, or <code>null</code> if no such
* special character should be processed as a value separator.
* The default is ":".
*/
public void setValueSeparator(String valueSeparator) {
this.valueSeparator = valueSeparator;
}
/**
* Set the system property mode by the name of the corresponding constant,
......@@ -218,84 +164,6 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
this.searchSystemEnvironment = searchSystemEnvironment;
}
/**
* Set whether to ignore unresolvable placeholders.
* <p>Default is "false": An exception will be thrown if a placeholder fails
* to resolve. Switch this flag to "true" in order to preserve the placeholder
* String as-is in such a case, leaving it up to other placeholder configurers
* to resolve it.
*/
public void setIgnoreUnresolvablePlaceholders(boolean ignoreUnresolvablePlaceholders) {
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
}
/**
* Set a value that should be treated as <code>null</code> when
* resolved as a placeholder value: e.g. "" (empty String) or "null".
* <p>Note that this will only apply to full property values,
* not to parts of concatenated values.
* <p>By default, no such null value is defined. This means that
* there is no way to express <code>null</code> as a property
* value unless you explictly map a corresponding value here.
*/
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
/**
* Only necessary to check that we're not parsing our own bean definition,
* to avoid failing on unresolvable placeholders in properties file locations.
* The latter case can happen with placeholders for system properties in
* resource locations.
* @see #setLocations
* @see org.springframework.core.io.ResourceEditor
*/
public void setBeanName(String beanName) {
this.beanName = beanName;
}
/**
* Only necessary to check that we're not parsing our own bean definition,
* to avoid failing on unresolvable placeholders in properties file locations.
* The latter case can happen with placeholders for system properties in
* resource locations.
* @see #setLocations
* @see org.springframework.core.io.ResourceEditor
*/
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
for (String curName : beanNames) {
// Check that we're not parsing our own bean definition,
// to avoid failing on unresolvable placeholders in properties file locations.
if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
try {
visitor.visitBeanDefinition(bd);
}
catch (Exception ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage());
}
}
}
// New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
beanFactoryToProcess.resolveAliases(valueResolver);
// New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}
/**
* Resolve the given placeholder using the given properties, performing
* a system properties check according to the given mode.
......@@ -379,30 +247,16 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
* Only retained for compatibility with Spring 2.5 extensions.
*/
@Deprecated
protected String parseStringValue(String strVal, Properties props, Set visitedPlaceholders) {
protected String parseStringValue(String strVal, Properties props, Set<?> visitedPlaceholders) {
PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper(
placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
PlaceholderResolver resolver = new PropertyPlaceholderConfigurerResolver(props);
return helper.replacePlaceholders(strVal, resolver);
}
private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
private final PropertyPlaceholderHelper helper;
private final PlaceholderResolver resolver;
public PlaceholderResolvingStringValueResolver(Properties props) {
this.helper = new PropertyPlaceholderHelper(
placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
this.resolver = new PropertyPlaceholderConfigurerResolver(props);
}
public String resolveStringValue(String strVal) throws BeansException {
String value = this.helper.replacePlaceholders(strVal, this.resolver);
return (value.equals(nullValue) ? null : value);
}
@Override
protected PlaceholderResolver getPlaceholderResolver(Properties props) {
return new PropertyPlaceholderConfigurerResolver(props);
}
......@@ -419,4 +273,5 @@ public class PropertyPlaceholderConfigurer extends PropertyResourceConfigurer
}
}
}
......@@ -166,7 +166,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
setParentBeanFactory(parentBeanFactory);
}
/**
* Set the instantiation strategy to use for creating bean instances.
* Default is CglibSubclassingInstantiationStrategy.
......
......@@ -21,8 +21,10 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
......@@ -40,7 +42,7 @@ import org.springframework.util.Assert;
* @since 11.12.2003
* @see BeanDefinitionReaderUtils
*/
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader {
public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
......@@ -51,6 +53,8 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
private ClassLoader beanClassLoader;
private Environment environment = new DefaultEnvironment();
private BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
......@@ -62,9 +66,14 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
* {@link org.springframework.context.ApplicationContext} implementations.
* <p>If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a
* {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
* <p>If the the passed-in bean factory also implements {@link EnvironmentCapable} its
* environment will be used by this reader. Otherwise, the reader will initialize and
* use a {@link DefaultEnvironment}. All ApplicationContext implementations are
* EnvironmentCapable, while normal BeanFactory implementations are not.
* @param registry the BeanFactory to load bean definitions into,
* in the form of a BeanDefinitionRegistry
* @see #setResourceLoader
* @see #setEnvironment
*/
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
......@@ -77,6 +86,14 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// Inherit Environment if possible
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable)this.registry).getEnvironment();
}
else {
this.environment = new DefaultEnvironment();
}
}
......@@ -122,6 +139,21 @@ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionRead
return this.beanClassLoader;
}
/**
* TODO SPR-7508: document
* @param environment
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* TODO SPR-7508: document
*/
public Environment getEnvironment() {
return this.environment;
}
/**
* Set the BeanNameGenerator to use for anonymous beans
* (without explicit bean name specified).
......
......@@ -68,6 +68,9 @@ import org.springframework.beans.factory.config.Scope;
import org.springframework.core.DecoratingClassLoader;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
......@@ -100,6 +103,7 @@ import org.springframework.util.StringValueResolver;
* @author Rod Johnson
* @author Juergen Hoeller
* @author Costin Leau
* @author Chris Beams
* @since 15 April 2001
* @see #getBeanDefinition
* @see #createBean
......@@ -166,6 +170,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<Object>("Prototype beans currently in creation");
private ConfigurableEnvironment environment = new DefaultEnvironment();
/**
* Create a new AbstractBeanFactory.
*/
......@@ -189,7 +196,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
......@@ -682,7 +689,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.propertyEditorRegistrars;
}
public void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
Assert.notNull(requiredType, "Required type must not be null");
Assert.isAssignable(PropertyEditor.class, propertyEditorClass);
this.customEditors.put(requiredType, propertyEditorClass);
......@@ -1253,7 +1260,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException {
if (!ObjectUtils.isEmpty(typesToMatch)) {
ClassLoader tempClassLoader = getTempClassLoader();
......
......@@ -203,6 +203,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
*/
public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
// TODO SPR-7515: should also do EnvironmentAware injection here?
if (autowireCandidateResolver instanceof BeanFactoryAware) {
if (System.getSecurityManager() != null) {
final BeanFactory target = this;
......@@ -460,7 +461,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
// Implementation of ConfigurableListableBeanFactory interface
//---------------------------------------------------------------------
public void registerResolvableDependency(Class dependencyType, Object autowiredValue) {
public void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue) {
Assert.notNull(dependencyType, "Type must not be null");
if (autowiredValue != null) {
Assert.isTrue((autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue)),
......
......@@ -43,6 +43,6 @@ public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName);
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}
......@@ -33,6 +33,8 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.util.StringUtils;
/**
......@@ -59,6 +61,9 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
/** Map from bean name to bean instance */
private final Map<String, Object> beans = new HashMap<String, Object>();
/** TODO SPR-7508: document */
private ConfigurableEnvironment environment = new DefaultEnvironment();
/**
* Add a new singleton bean.
......
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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.
......@@ -63,7 +63,7 @@ public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDef
if (parentName != null) {
builder.getRawBeanDefinition().setParentName(parentName);
}
Class beanClass = getBeanClass(element);
Class<?> beanClass = getBeanClass(element);
if (beanClass != null) {
builder.getRawBeanDefinition().setBeanClass(beanClass);
}
......@@ -111,7 +111,7 @@ public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDef
* the supplied <code>Element</code>, or <code>null</code> if none
* @see #getBeanClassName
*/
protected Class getBeanClass(Element element) {
protected Class<?> getBeanClass(Element element) {
return null;
}
......
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2010 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.
......@@ -42,7 +42,7 @@ public interface BeanDefinitionParser {
/**
* Parse the specified {@link Element} and register the resulting
* {@link BeanDefinition BeanDefinition(s)} with the
* {@link org.springframework.beans.factory.xml.ParserContext#getRegistry()} BeanDefinitionRegistry}
* {@link org.springframework.beans.factory.xml.ParserContext#getRegistry() BeanDefinitionRegistry}
* embedded in the supplied {@link ParserContext}.
* <p>Implementations must return the primary {@link BeanDefinition} that results
* from the parse if they will ever be used in a nested fashion (for example as
......@@ -50,7 +50,8 @@ public interface BeanDefinitionParser {
* <code>null</code> if they will <strong>not</strong> be used in a nested fashion.
* @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions}
* @param parserContext the object encapsulating the current state of the parsing process;
* provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
* provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry
* BeanDefinitionRegistry}.
* @return the primary {@link BeanDefinition}
*/
BeanDefinition parse(Element element, ParserContext parserContext);
......
......@@ -58,6 +58,7 @@ import org.springframework.beans.factory.support.ManagedProperties;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.support.MethodOverrides;
import org.springframework.beans.factory.support.ReplaceOverride;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
......@@ -92,10 +93,14 @@ public class BeanDefinitionParserDelegate {
*/
public static final String TRUE_VALUE = "true";
public static final String FALSE_VALUE = "false";
public static final String DEFAULT_VALUE = "default";
public static final String DESCRIPTION_ELEMENT = "description";
public static final String AUTOWIRE_NO_VALUE = "no";
public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
......@@ -239,19 +244,25 @@ public class BeanDefinitionParserDelegate {
private final ParseState parseState = new ParseState();
private Environment environment;
/**
* Stores all used bean names so we can enforce uniqueness on a per file basis.
* Stores all used bean names so we can enforce uniqueness on a per
* beans-element basis. Duplicate bean ids/names may not exist within the
* same level of beans element nesting, but may be duplicated across levels.
*/
private final Set<String> usedNames = new HashSet<String>();
/**
* Create a new BeanDefinitionParserDelegate associated with the
* supplied {@link XmlReaderContext}.
* supplied {@link XmlReaderContext} and {@link Environment}.
*/
public BeanDefinitionParserDelegate(XmlReaderContext readerContext) {
public BeanDefinitionParserDelegate(XmlReaderContext readerContext, Environment environment) {
Assert.notNull(readerContext, "XmlReaderContext must not be null");
Assert.notNull(readerContext, "Environment must not be null");
this.readerContext = readerContext;
this.environment = environment;
}
/**
......@@ -261,6 +272,12 @@ public class BeanDefinitionParserDelegate {
return this.readerContext;
}
/**
* Get the {@link Environment} associated with this helper instance.
*/
public final Environment getEnvironment() {
return this.environment;
}
/**
* Invoke the {@link org.springframework.beans.factory.parsing.SourceExtractor} to pull the
......@@ -294,33 +311,69 @@ public class BeanDefinitionParserDelegate {
/**
* Initialize the default lazy-init, autowire, dependency check settings,
* init-method, destroy-method and merge settings.
* @see #populateDefaults(DocumentDefaultsDefinition, org.w3c.dom.Element)
* init-method, destroy-method and merge settings. Support nested 'beans'
* element use cases by falling back to <literal>parent</literal> in case the
* defaults are not explicitly set locally.
* @see #populateDefaults(DocumentDefaultsDefinition, DocumentDefaultsDefinition, org.w3c.dom.Element)
* @see #getDefaults()
*/
public void initDefaults(Element root) {
populateDefaults(this.defaults, root);
public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
this.readerContext.fireDefaultsRegistered(this.defaults);
}
/**
* Populate the given DocumentDefaultsDefinition instance with the default lazy-init,
* autowire, dependency check settings, init-method, destroy-method and merge settings.
* Support nested 'beans' element use cases by falling back to
* <literal>parentDefaults</literal> in case the defaults are not explicitly set
* locally.
* @param defaults the defaults to populate
* @param defaults the parent BeanDefinitionParserDelegate (if any) defaults to fall back to
* @param root the root element of the current bean definition document (or nested beans element)
*/
protected void populateDefaults(DocumentDefaultsDefinition defaults, Element root) {
defaults.setLazyInit(root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE));
defaults.setMerge(root.getAttribute(DEFAULT_MERGE_ATTRIBUTE));
defaults.setAutowire(root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE));
protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE;
}
defaults.setLazyInit(lazyInit);
String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
if (DEFAULT_VALUE.equals(merge)) {
merge = parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE;
}
defaults.setMerge(merge);
String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
if (DEFAULT_VALUE.equals(autowire)) {
autowire = parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE;
}
defaults.setAutowire(autowire);
// don't fall back to parentDefaults for dependency-check as it's no
// longer supported in <beans> as of 3.0. Therefore, no nested <beans>
// would ever need to fall back to it.
defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
} else if (parentDefaults != null) {
defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
}
if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
} else if (parentDefaults != null) {
defaults.setInitMethod(parentDefaults.getInitMethod());
}
if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
} else if (parentDefaults != null) {
defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
}
defaults.setSource(this.readerContext.extractSource(root));
}
......@@ -431,7 +484,8 @@ public class BeanDefinitionParserDelegate {
}
/**
* Validate that the specified bean name and aliases have not been used already.
* Validate that the specified bean name and aliases have not been used already
* within the current level of beans element nesting.
*/
protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
String foundName = null;
......@@ -443,7 +497,7 @@ public class BeanDefinitionParserDelegate {
foundName = (String) CollectionUtils.findFirstMatch(this.usedNames, aliases);
}
if (foundName != null) {
error("Bean name '" + foundName + "' is already used in this file", beanElement);
error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);
}
this.usedNames.add(beanName);
......
......@@ -16,6 +16,9 @@
package org.springframework.beans.factory.xml;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
import static org.springframework.util.StringUtils.trimAllWhitespace;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.LinkedHashSet;
......@@ -32,11 +35,11 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.SystemPropertyUtils;
/**
* Default implementation of the {@link BeanDefinitionDocumentReader} interface.
......@@ -59,6 +62,8 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;
public static final String NESTED_BEANS_ELEMENT = "beans";
public static final String ALIAS_ELEMENT = "alias";
public static final String NAME_ATTRIBUTE = "name";
......@@ -69,14 +74,29 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
public static final String RESOURCE_ATTRIBUTE = "resource";
/** @see org.springframework.context.annotation.Profile */
public static final String PROFILE_ATTRIBUTE = "profile";
protected final Log logger = LogFactory.getLog(getClass());
private XmlReaderContext readerContext;
private Environment environment;
private BeanDefinitionParserDelegate delegate;
/**
* Parses bean definitions according to the "spring-beans" DTD.
* TODO SPR-7508: document
* @param environment
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* Parses bean definitions according to the "spring-beans" DTD. TODO SPR-7508 XSD
* <p>Opens a DOM Document; then initializes the default settings
* specified at <code>&lt;beans&gt;</code> level; then parses
* the contained bean definitions.
......@@ -87,16 +107,49 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
boolean isCandidate = false;
if (profileSpec == null || profileSpec.equals("")) {
isCandidate = true;
} else {
String[] profiles = commaDelimitedListToStringArray(trimAllWhitespace(profileSpec));
for (String profile : profiles) {
if (this.environment.getActiveProfiles().contains(profile)) {
isCandidate = true;
break;
}
}
}
if (!isCandidate) {
// TODO SPR-7508 logging
// logger.debug(format("XML is targeted for environment [%s], but current environment is [%s]. Skipping", targetEnvironment, environment == null ? null : environment.getName()));
return;
}
// any nested <beans> elements will cause recursion in this method. in
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createHelper(readerContext, root, parent);
preProcessXml(root);
parseBeanDefinitions(root, delegate);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root);
protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext, environment);
delegate.initDefaults(root, parentDelegate);
return delegate;
}
......@@ -152,6 +205,10 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
/**
......@@ -166,7 +223,7 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
}
// Resolve system properties: e.g. "${user.dir}"
location = SystemPropertyUtils.resolvePlaceholders(location);
location = environment.resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<Resource>(4);
......
......@@ -65,6 +65,7 @@ import org.springframework.util.xml.XmlValidationModeDetector;
*
* @author Juergen Hoeller
* @author Rob Harrop
* @author Chris Beams
* @since 26.11.2003
* @see #setDocumentReaderClass
* @see BeanDefinitionDocumentReader
......@@ -103,7 +104,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
private boolean namespaceAware = false;
private Class documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
private ProblemReporter problemReporter = new FailFastProblemReporter();
......@@ -134,7 +135,6 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
super(registry);
}
/**
* Set whether to use XML validation. Default is <code>true</code>.
* <p>This method switches namespace awareness on if validation is turned off,
......@@ -283,7 +283,7 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
* <p>The default is {@link DefaultBeanDefinitionDocumentReader}.
* @param documentReaderClass the desired BeanDefinitionDocumentReader implementation class
*/
public void setDocumentReaderClass(Class documentReaderClass) {
public void setDocumentReaderClass(Class<?> documentReaderClass) {
if (documentReaderClass == null || !BeanDefinitionDocumentReader.class.isAssignableFrom(documentReaderClass)) {
throw new IllegalArgumentException(
"documentReaderClass must be an implementation of the BeanDefinitionDocumentReader interface");
......@@ -487,8 +487,12 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
* @see BeanDefinitionDocumentReader#registerBeanDefinitions
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// Read document based on new BeanDefinitionDocumentReader SPI.
// Read document based on new BeanDefinitionDocumentReader SPI. // TODO SPR-7508: polish - remove comment
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// TODO SPR-7508: remove ugly cast
if (documentReader instanceof DefaultBeanDefinitionDocumentReader) {
((DefaultBeanDefinitionDocumentReader)documentReader).setEnvironment(this.getEnvironment());
}
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
......@@ -500,7 +504,6 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
* <p>The default implementation instantiates the specified "documentReaderClass".
* @see #setDocumentReaderClass
*/
@SuppressWarnings("unchecked")
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
......
......@@ -19,6 +19,7 @@ package org.springframework.beans.factory.xml;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
/**
......@@ -34,7 +35,7 @@ import org.springframework.core.io.Resource;
* <p>This class registers each bean definition with the {@link DefaultListableBeanFactory}
* superclass, and relies on the latter's implementation of the {@link BeanFactory} interface.
* It supports singletons, prototypes, and references to either of these kinds of bean.
* See "spring-beans-2.0.dtd" for details on options and configuration style.
* See "spring-beans-2.0.dtd" for details on options and configuration style. // TODO SPR-7508 polish - s/dtd/xsd/
*
* <p><b>For advanced needs, consider using a {@link DefaultListableBeanFactory} with
* an {@link XmlBeanDefinitionReader}.</b> The latter allows for reading from multiple XML
......@@ -42,10 +43,14 @@ import org.springframework.core.io.Resource;
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Chris Beams
* @since 15 April 2001
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
* @see XmlBeanDefinitionReader
* @deprecated as of Spring 3.1 in favor of {@link DefaultListableBeanFactory} and
* {@link XmlBeanDefinitionReader}
*/
@Deprecated
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
......@@ -58,7 +63,7 @@ public class XmlBeanFactory extends DefaultListableBeanFactory {
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
this(resource, (BeanFactory)null);
}
/**
......
......@@ -34,6 +34,8 @@ import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.URIEditor;
import org.springframework.beans.propertyeditors.URLEditor;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
......@@ -53,18 +55,36 @@ import org.springframework.core.io.support.ResourcePatternResolver;
*/
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
private final Environment environment;
private final ResourceLoader resourceLoader;
/**
* Create a new ResourceEditorRegistrar for the given ResourceLoader
* Create a new ResourceEditorRegistrar for the given {@link ResourceLoader}
* using a {@link DefaultEnvironment}.
* @param resourceLoader the ResourceLoader (or ResourcePatternResolver)
* to create editors for (usually an ApplicationContext)
* @see org.springframework.core.io.support.ResourcePatternResolver
* @see org.springframework.context.ApplicationContext
* @deprecated as of Spring 3.1 in favor of
* {@link ResourceEditorRegistrar#ResourceEditorRegistrar(ResourceLoader, Environment)}
*/
@Deprecated
public ResourceEditorRegistrar(ResourceLoader resourceLoader) {
this(resourceLoader, new DefaultEnvironment());
}
/**
* Create a new ResourceEditorRegistrar for the given ResourceLoader
* @param resourceLoader the ResourceLoader (or ResourcePatternResolver)
* to create editors for (usually an ApplicationContext)
* @see org.springframework.core.io.support.ResourcePatternResolver
* @see org.springframework.context.ApplicationContext
*/
public ResourceEditorRegistrar(ResourceLoader resourceLoader, Environment environment) {
this.resourceLoader = resourceLoader;
this.environment = environment;
}
......@@ -82,7 +102,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
* @see org.springframework.core.io.support.ResourceArrayPropertyEditor
*/
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader);
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.environment);
doRegisterEditor(registry, Resource.class, baseEditor);
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
......@@ -96,7 +116,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
if (this.resourceLoader instanceof ResourcePatternResolver) {
doRegisterEditor(registry, Resource[].class,
new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader));
new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.environment));
}
}
......
http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
http\://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/tool"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.springframework.org/schema/tool"
elementFormDefault="qualified">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the tool support annotations for Spring's configuration namespaces.
Used in other namespace XSD files; not intended for direct use in config files.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="annotation">
<xsd:complexType>
<xsd:sequence minOccurs="0">
<xsd:element name="expected-type" type="typedParameterType" minOccurs="0" maxOccurs="1"/>
<xsd:element name="assignable-to" type="assignableToType" minOccurs="0" maxOccurs="1"/>
<xsd:element name="exports" type="exportsType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="registers-scope" type="registersScopeType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="expected-method" type="expectedMethodType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="kind" default="direct">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ref"/>
<xsd:enumeration value="direct"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="typedParameterType">
<xsd:attribute name="type" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="assignableToType">
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="restriction" default="both">
<xsd:simpleType>
<xsd:restriction base="xsd:NMTOKEN">
<xsd:enumeration value="both"/>
<xsd:enumeration value="interface-only"/>
<xsd:enumeration value="class-only"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="expectedMethodType">
<xsd:attribute name="type" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines an XPath query that can be executed against the node annotated with this
type to determine the class for which the this method is valid
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="type-ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines an XPath query that can be executed against the node annotated with this
type to determine a referenced bean (by id or alias) for which the given method is valid
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines an AspectJ method execution pointcut expressions that matches valid methods
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="exportsType">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates that an annotated type exports an application visible component.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="type" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The type of the exported component. May be null if the type is not known until runtime.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="identifier" type="xsd:string" default="@id">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines an XPath query that can be executed against the node annotated with this
type to determine the identifier of any exported component.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="registersScopeType">
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the name of a custom bean scope that the annotated type registers, e.g. "conversation".
Such a scope will be available in addition to the standard "singleton" and "prototype" scopes
(plus "request", "session" and "globalSession" in a web application environment).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/util"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/util"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.1.xsd"/>
<xsd:element name="constant">
<xsd:annotation>
<xsd:documentation>
Reference a public, static field on a type and expose its value as
a bean. For example <code>&lt;util:constant static-field=&quot;java.lang.Integer.MAX_VALUE&quot;/&gt;</code>.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="static-field" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="property-path">
<xsd:annotation>
<xsd:documentation>
Reference a property on a bean (or as a nested value) and expose its values as
a bean. For example &lt;util:property-path path=&quot;order.customer.name&quot;/&gt;.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="path" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="list">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.beans.factory.config.ListFactoryBean">
Builds a List instance of the specified type, populated with the specified content.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="java.util.List"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:listOrSetType">
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="list-class" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:expected-type type="java.lang.Class"/>
<tool:assignable-to type="java.util.List"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scope" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The scope of this collection bean: typically "singleton" (one shared instance,
which will be returned by all calls to getBean with the given id), or
"prototype" (independent instance resulting from each call to getBean).
Default is "singleton". Further scopes, such as "request" or "session",
might be supported by extended bean factories (e.g. in a web environment).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="set">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.beans.factory.config.SetFactoryBean">
Builds a Set instance of the specified type, populated with the specified content.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="java.util.Set"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:listOrSetType">
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="set-class" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:expected-type type="java.lang.Class"/>
<tool:assignable-to type="java.util.Set"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scope" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The scope of this collection bean: typically "singleton" (one shared instance,
which will be returned by all calls to getBean with the given id), or
"prototype" (independent instance resulting from each call to getBean).
Default is "singleton". Further scopes, such as "request" or "session",
might be supported by extended bean factories (e.g. in a web environment).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="map">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.beans.factory.config.MapFactoryBean">
Builds a Map instance of the specified type, populated with the specified content.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="java.util.Map"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:mapType">
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="map-class" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:expected-type type="java.lang.Class"/>
<tool:assignable-to type="java.util.Map"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scope" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The scope of this collection bean: typically "singleton" (one shared instance,
which will be returned by all calls to getBean with the given id), or
"prototype" (independent instance resulting from each call to getBean).
Default is "singleton". Further scopes, such as "request" or "session",
might be supported by extended bean factories (e.g. in a web environment).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="properties">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.beans.factory.config.PropertiesFactoryBean">
Loads a Properties instance from the resource location specified by the '<code>location</code>' attribute.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="java.util.Properties"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:propsType">
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="location" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:expected-type type="org.springframework.core.io.Resource"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="local-override" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies whether local properties override properties from files.
Default is "false": properties from files override local defaults.
If set to "true", local properties will override defaults from files.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scope" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The scope of this collection bean: typically "singleton" (one shared instance,
which will be returned by all calls to getBean with the given id), or
"prototype" (independent instance resulting from each call to getBean).
Default is "singleton". Further scopes, such as "request" or "session",
might be supported by extended bean factories (e.g. in a web environment).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.config;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ByteArrayResource;
import test.beans.TestBean;
/**
* Tests cornering SPR-7547.
* Unit tests for {@link EnvironmentAwarePropertyPlaceholderConfigurer}.
*
* @see PropertyResourceConfigurerTests
* @author Chris Beams
*/
public class PropertyPlaceholderConfigurerTests {
private static final String P1 = "p1";
private static final String P1_LOCAL_PROPS_VAL = "p1LocalPropsVal";
private static final String P1_SYSTEM_PROPS_VAL = "p1SystemPropsVal";
private static final String P1_SYSTEM_ENV_VAL = "p1SystemEnvVal";
private DefaultListableBeanFactory bf;
private AbstractPropertyPlaceholderConfigurer ppc;
private Properties ppcProperties;
private AbstractBeanDefinition p1BeanDef;
@Before
public void setUp() {
p1BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${"+P1+"}")
.getBeanDefinition();
bf = new DefaultListableBeanFactory();
ppcProperties = new Properties();
ppcProperties.setProperty(P1, P1_LOCAL_PROPS_VAL);
System.setProperty(P1, P1_SYSTEM_PROPS_VAL);
getModifiableSystemEnvironment().put(P1, P1_SYSTEM_ENV_VAL);
ppc = new PropertyPlaceholderConfigurer();
ppc.setProperties(ppcProperties);
}
@After
public void tearDown() {
System.clearProperty(P1);
getModifiableSystemEnvironment().remove(P1);
}
// -------------------------------------------------------------------------
// Tests to ensure backward-compatibility for Environment refactoring
// -------------------------------------------------------------------------
@Test
public void resolveFromSystemProperties() {
getModifiableSystemEnvironment().put("otherKey", "systemValue");
p1BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${"+P1+"}")
.addPropertyValue("sex", "${otherKey}")
.getBeanDefinition();
registerWithGeneratedName(p1BeanDef, bf);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
assertThat(bean.getSex(), equalTo("systemValue"));
getModifiableSystemEnvironment().remove("otherKey");
}
@Test
public void resolveFromLocalProperties() {
tearDown(); // eliminate entries from system props/environment
registerWithGeneratedName(p1BeanDef, bf);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
}
@Test
public void setSystemPropertiesMode_defaultIsFallback() {
registerWithGeneratedName(p1BeanDef, bf);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
}
/*
@Test
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemProperties() {
registerWithGeneratedName(p1BeanDef, bf);
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_SYSTEM_PROPS_VAL));
}
@Test
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemEnvironment() {
registerWithGeneratedName(p1BeanDef, bf);
System.clearProperty(P1); // will now fall all the way back to system environment
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_SYSTEM_ENV_VAL));
}
@Test
public void setSystemSystemPropertiesMode_toOverride_andSetSearchSystemEnvironment_toFalse() {
registerWithGeneratedName(p1BeanDef, bf);
System.clearProperty(P1); // will now fall all the way back to system environment
ppc.setSearchSystemEnvironment(false);
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL)); // has to resort to local props
}
*/
/**
* Prior to the fix for SPR-7547, the following would throw
* IllegalStateException because the PropertiesLoaderSupport base class
* assumed ByteArrayResource implements Resource.getFilename(). It does
* not, and AbstractResource.getFilename() is called instead, raising the
* exception. The following now works, as getFilename() is called in a
* try/catch to check whether the resource is actually file-based or not.
*
* See SPR-7552, which suggests paths to address the root issue rather than
* just patching the problem.
* Creates a scenario in which two PPCs are configured, each with different
* settings regarding resolving properties from the environment.
*/
@Test
public void repro() {
public void twoPlacholderConfigurers_withConflictingSettings() {
String P2 = "p2";
String P2_LOCAL_PROPS_VAL = "p2LocalPropsVal";
String P2_SYSTEM_PROPS_VAL = "p2SystemPropsVal";
String P2_SYSTEM_ENV_VAL = "p2SystemEnvVal";
AbstractBeanDefinition p2BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${"+P1+"}")
.addPropertyValue("country", "${"+P2+"}")
.getBeanDefinition();
bf.registerBeanDefinition("p1Bean", p1BeanDef);
bf.registerBeanDefinition("p2Bean", p2BeanDef);
ppc.setIgnoreUnresolvablePlaceholders(true);
ppc.postProcessBeanFactory(bf);
System.setProperty(P2, P2_SYSTEM_PROPS_VAL);
getModifiableSystemEnvironment().put(P2, P2_SYSTEM_ENV_VAL);
Properties ppc2Properties = new Properties();
ppc2Properties.put(P2, P2_LOCAL_PROPS_VAL);
PropertyPlaceholderConfigurer ppc2 = new PropertyPlaceholderConfigurer();
ppc2.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc2.setProperties(ppc2Properties);
ppc2Properties = new Properties();
ppc2Properties.setProperty(P2, P2_LOCAL_PROPS_VAL);
ppc2.postProcessBeanFactory(bf);
TestBean p1Bean = bf.getBean("p1Bean", TestBean.class);
assertThat(p1Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
TestBean p2Bean = bf.getBean("p2Bean", TestBean.class);
assertThat(p2Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
assertThat(p2Bean.getCountry(), equalTo(P2_SYSTEM_PROPS_VAL));
System.clearProperty(P2);
getModifiableSystemEnvironment().remove(P2);
}
@Test
public void customPlaceholderPrefixAndSuffix() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setPlaceholderPrefix("@<");
ppc.setPlaceholderSuffix(">");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",
rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}").getBeanDefinition());
.addPropertyValue("name", "@<key1>")
.addPropertyValue("sex", "${key2}")
.getBeanDefinition());
System.setProperty("key1", "systemKey1Value");
System.setProperty("key2", "systemKey2Value");
ppc.postProcessBeanFactory(bf);
System.clearProperty("key1");
System.clearProperty("key2");
assertThat(bf.getBean(TestBean.class).getName(), is("systemKey1Value"));
assertThat(bf.getBean(TestBean.class).getSex(), is("${key2}"));
}
@Test
public void nullValueIsPreserved() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocation(new ByteArrayResource("my.name=Inigo Montoya".getBytes()));
ppc.setNullValue("customNull");
getModifiableSystemEnvironment().put("my.name", "customNull");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), nullValue());
getModifiableSystemEnvironment().remove("my.name");
}
// -------------------------------------------------------------------------
// Tests for functionality not possible prior to Environment refactoring
// -------------------------------------------------------------------------
/**
* Tests that properties against a BeanFactory's Environment are used by
* PropertyPlaceholderConfigurer during placeholder resolution.
@Test @SuppressWarnings({ "unchecked", "rawtypes", "serial" })
public void replacePlaceholdersFromBeanFactoryEnvironmentPropertySources() {
System.setProperty("key1", "systemValue");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.getEnvironment().addPropertySource("psCustom", new HashMap() {{ put("key1", "customValue"); }});
bf.registerBeanDefinition("testBean",
rootBeanDefinition(TestBean.class).addPropertyValue("name", "${key1}").getBeanDefinition());
new PropertyPlaceholderConfigurer().postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), is("customValue"));
System.clearProperty("key1");
}
*/
// -------------------------------------------------------------------------
// Utilities
// -------------------------------------------------------------------------
TestBean testBean = bf.getBean(TestBean.class);
assertThat(testBean.getName(), equalTo("Inigo Montoya"));
// TODO SPR-7508: duplicated from EnvironmentPropertyResolutionSearchTests
@SuppressWarnings("unchecked")
private static Map<String, String> getModifiableSystemEnvironment() {
Class<?>[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for (Class<?> cl : classes) {
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
try {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
return (Map<String, String>) obj;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
throw new IllegalStateException();
}
}
......@@ -16,6 +16,14 @@
package org.springframework.beans.factory.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
import static test.util.TestResourceUtils.qualifiedResource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
......@@ -23,18 +31,12 @@ import java.util.Properties;
import java.util.Set;
import java.util.prefs.Preferences;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import test.beans.IndexedTestBean;
import test.beans.TestBean;
import static test.util.TestResourceUtils.*;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.ManagedList;
......@@ -43,11 +45,15 @@ import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.io.Resource;
import test.beans.IndexedTestBean;
import test.beans.TestBean;
/**
* Unit tests for various {@link PropertyResourceConfigurer} implementations including:
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
* {@link PreferencesPlaceholderConfigurer}.
*
* @see PropertyPlaceholderConfigurerTests
* @since 02.10.2003
* @author Juergen Hoeller
* @author Chris Beams
......@@ -794,6 +800,39 @@ public final class PropertyResourceConfigurerTests {
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
}
/* TODO SPR-7508: uncomment after EnvironmentAwarePropertyPlaceholderConfigurer implementation
@Test
public void testPreferencesPlaceholderConfigurerWithCustomPropertiesInEnvironment() {
factory.registerBeanDefinition("tb",
genericBeanDefinition(TestBean.class)
.addPropertyValue("name", "${mypath/myName}")
.addPropertyValue("age", "${myAge}")
.addPropertyValue("touchy", "${myotherpath/myTouchy}")
.getBeanDefinition());
Properties props = new Properties();
props.put("myAge", "99");
factory.getEnvironment().getPropertySources().add(new PropertiesPropertySource("localProps", props));
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
ppc.setSystemTreePath("mySystemPath");
ppc.setUserTreePath("myUserPath");
Preferences.systemRoot().node("mySystemPath").node("mypath").put("myName", "myNameValue");
Preferences.systemRoot().node("mySystemPath/myotherpath").put("myTouchy", "myTouchyValue");
Preferences.userRoot().node("myUserPath/myotherpath").put("myTouchy", "myOtherTouchyValue");
ppc.afterPropertiesSet();
ppc.postProcessBeanFactory(factory);
TestBean tb = (TestBean) factory.getBean("tb");
assertEquals("myNameValue", tb.getName());
assertEquals(99, tb.getAge());
assertEquals("myOtherTouchyValue", tb.getTouchy());
Preferences.userRoot().node("myUserPath/myotherpath").remove("myTouchy");
Preferences.systemRoot().node("mySystemPath/myotherpath").remove("myTouchy");
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
}
*/
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
......
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="testBean" class="test.beans.TestBean">
<property name="name" value="topLevel"/>
</bean>
<beans>
<bean id="testBean" class="test.beans.TestBean">
<property name="name" value="nested"/>
</bean>
</beans>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="testBean" class="test.beans.TestBean">
<property name="name" value="original"/>
</bean>
<!-- STS should raise an error for this duplicate id -->
<bean id="testBean" class="test.beans.TestBean">
<property name="name" value="duplicate"/>
</bean>
</beans>
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ClassPathResource;
import test.beans.TestBean;
/**
* With Spring 3.1, bean id attributes (and all other id attributes across the
* core schemas) are no longer typed as xsd:id, but as xsd:string. This allows
* for using the same bean id within nested <beans> elements.
*
* Duplicate ids *within the same level of nesting* will still be treated as an
* error through the ProblemReporter, as this could never be an intended/valid
* situation.
*
* @author Chris Beams
* @since 3.1
* @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateName
* @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateNameInAlias
*/
public class DuplicateBeanIdTests {
@Test
public void duplicateBeanIdsWithinSameNestingLevelRaisesError() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
try {
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-sameLevel-context.xml", this.getClass()));
fail("expected parsing exception due to duplicate ids in same nesting level");
} catch (Exception ex) {
// expected
}
}
@Test
public void duplicateBeanIdsAcrossNestingLevels() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-multiLevel-context.xml", this.getClass()));
TestBean testBean = bf.getBean(TestBean.class); // there should be only one
assertThat(testBean.getName(), equalTo("nested"));
}
}
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.internal.matchers.TypeSafeMatcher;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.io.ClassPathResource;
/**
* TODO SPR-7508: document
*
* @author Chris Beams
*/
public class EnvironmentBeansTests {
private static final String PROD_ELIGIBLE_XML = "environmentBeans-prodProfile.xml";
private static final String DEV_ELIGIBLE_XML = "environmentBeans-devProfile.xml";
private static final String ALL_ELIGIBLE_XML = "environmentBeans-noProfile.xml";
private static final String MULTI_ELIGIBLE_XML = "environmentBeans-multiProfile.xml";
private static final String UNKOWN_ELIGIBLE_XML = "environmentBeans-unknownProfile.xml";
private static final String PROD_ACTIVE = "prod";
private static final String DEV_ACTIVE = "dev";
private static final String NULL_ACTIVE = null;
private static final String UNKNOWN_ACTIVE = "unknown";
private static final String[] NONE_ACTIVE = new String[0];
private static final String[] MULTI_ACTIVE = new String[] { PROD_ACTIVE, DEV_ACTIVE };
private static final String TARGET_BEAN = "foo";
@Test
public void test() {
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, DEV_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, PROD_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NONE_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NULL_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, UNKNOWN_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(UNKOWN_ELIGIBLE_XML, MULTI_ACTIVE), not(containsTargetBean()));
}
private BeanDefinitionRegistry beanFactoryFor(String xmlName, String... activeProfileNames) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
DefaultEnvironment env = new DefaultEnvironment();
env.setActiveProfiles(activeProfileNames);
reader.setEnvironment(env);
reader.loadBeanDefinitions(new ClassPathResource(xmlName, getClass()));
return beanFactory;
}
private static Matcher<BeanDefinitionRegistry> containsBeanDefinition(final String beanName) {
return new TypeSafeMatcher<BeanDefinitionRegistry>() {
public void describeTo(Description desc) {
desc.appendText("a BeanDefinitionRegistry containing bean named ")
.appendValue(beanName);
}
@Override
public boolean matchesSafely(BeanDefinitionRegistry beanFactory) {
return beanFactory.containsBeanDefinition(beanName);
}
};
}
private static Matcher<BeanDefinitionRegistry> containsTargetBean() {
return containsBeanDefinition(TARGET_BEAN);
}
}
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ClassPathResource;
import test.beans.TestBean;
/**
* Tests for propagating enclosing beans element defaults to nested beans elements.
*
* @author Chris Beams
*/
public class NestedBeansElementAttributeRecursionTests {
@Test
public void defaultLazyInit() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-lazy-context.xml", this.getClass()));
BeanDefinition foo = bf.getBeanDefinition("foo");
BeanDefinition bar = bf.getBeanDefinition("bar");
BeanDefinition baz = bf.getBeanDefinition("baz");
BeanDefinition biz = bf.getBeanDefinition("biz");
BeanDefinition buz = bf.getBeanDefinition("buz");
assertThat(foo.isLazyInit(), is(false));
assertThat(bar.isLazyInit(), is(true));
assertThat(baz.isLazyInit(), is(false));
assertThat(biz.isLazyInit(), is(true));
assertThat(buz.isLazyInit(), is(true));
}
@Test
@SuppressWarnings("unchecked")
public void defaultMerge() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-merge-context.xml", this.getClass()));
TestBean topLevel = bf.getBean("topLevelConcreteTestBean", TestBean.class);
// has the concrete child bean values
assertThat(topLevel.getSomeList(), hasItems("charlie", "delta"));
// but does not merge the parent values
assertThat(topLevel.getSomeList(), not(hasItems("alpha", "bravo")));
TestBean firstLevel = bf.getBean("firstLevelNestedTestBean", TestBean.class);
// merges all values
assertThat(firstLevel.getSomeList(),
hasItems("charlie", "delta", "echo", "foxtrot"));
TestBean secondLevel = bf.getBean("secondLevelNestedTestBean", TestBean.class);
// merges all values
assertThat(secondLevel.getSomeList(),
hasItems("charlie", "delta", "echo", "foxtrot", "golf", "hotel"));
}
@Test
public void defaultAutowireCandidates() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-autowire-candidates-context.xml", this.getClass()));
assertThat(bf.getBeanDefinition("fooService").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("fooRepository").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("other").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("barService").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("fooController").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("bizRepository").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("bizService").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("bazService").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("random").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("fooComponent").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("fRepository").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("aComponent").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("someService").isAutowireCandidate(), is(false));
}
@Test
public void initMethod() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-init-destroy-context.xml", this.getClass()));
InitDestroyBean beanA = bf.getBean("beanA", InitDestroyBean.class);
InitDestroyBean beanB = bf.getBean("beanB", InitDestroyBean.class);
InitDestroyBean beanC = bf.getBean("beanC", InitDestroyBean.class);
InitDestroyBean beanD = bf.getBean("beanD", InitDestroyBean.class);
assertThat(beanA.initMethod1Called, is(true));
assertThat(beanB.initMethod2Called, is(true));
assertThat(beanC.initMethod3Called, is(true));
assertThat(beanD.initMethod2Called, is(true));
bf.destroySingletons();
assertThat(beanA.destroyMethod1Called, is(true));
assertThat(beanB.destroyMethod2Called, is(true));
assertThat(beanC.destroyMethod3Called, is(true));
assertThat(beanD.destroyMethod2Called, is(true));
}
}
class InitDestroyBean {
boolean initMethod1Called;
boolean initMethod2Called;
boolean initMethod3Called;
boolean destroyMethod1Called;
boolean destroyMethod2Called;
boolean destroyMethod3Called;
void initMethod1() { this.initMethod1Called = true; }
void initMethod2() { this.initMethod2Called = true; }
void initMethod3() { this.initMethod3Called = true; }
void destroyMethod1() { this.destroyMethod1Called = true; }
void destroyMethod2() { this.destroyMethod2Called = true; }
void destroyMethod3() { this.destroyMethod3Called = true; }
}
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
* Tests for new nested beans element support in Spring XML
*
* @author Chris Beams
*/
public class NestedBeansElementTests {
private final Resource XML =
new ClassPathResource("NestedBeansElementTests-context.xml", this.getClass());
@Test
public void getBean_withoutActiveProfile() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(XML);
Object foo = bf.getBean("foo");
assertThat(foo, instanceOf(String.class));
}
@Test
public void getBean_withActiveProfile() {
ConfigurableEnvironment env = new DefaultEnvironment();
env.setActiveProfiles("dev");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.setEnvironment(env);
reader.loadBeanDefinitions(XML);
bf.getBean("devOnlyBean"); // should not throw NSBDE
Object foo = bf.getBean("foo");
assertThat(foo, instanceOf(Integer.class));
bf.getBean("devOnlyBean");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
default-autowire-candidates="foo*">
<bean id="fooRepository" class="java.lang.Object"/>
<bean id="fooService" class="java.lang.Object"/>
<bean id="other" class="java.lang.Object"/>
<beans default-autowire-candidates="*Service">
<bean id="barService" class="java.lang.Object"/>
<bean id="fooController" class="java.lang.Object"/>
<beans default-autowire-candidates="*Repository">
<bean id="bizRepository" class="java.lang.Object"/>
<bean id="bizService" class="java.lang.Object"/>
</beans>
<beans> <!-- should inherit enclosing beans' defaults -->
<bean id="bazService" class="java.lang.Object"/>
<bean id="random" class="java.lang.Object"/>
<bean id="fooComponent" class="java.lang.Object"/>
<bean id="fRepository" class="java.lang.Object"/>
</beans>
<beans default-autowire-candidates="*Component">
<bean id="aComponent" class="java.lang.Object"/>
<bean id="someService" class="java.lang.Object"/>
</beans>
</beans>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="foo" class="java.lang.Object"/>
<beans default-autowire="constructor">
<bean id="bar" class="java.lang.Object"/>
<beans>
<bean id="baz" class="java.lang.Object"/>
</beans>
</beans>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
default-init-method="initMethod1"
default-destroy-method="destroyMethod1">
<bean id="beanA" class="org.springframework.beans.factory.xml.InitDestroyBean"/>
<beans default-init-method="initMethod2" default-destroy-method="destroyMethod2">
<bean id="beanB" class="org.springframework.beans.factory.xml.InitDestroyBean"/>
<beans default-init-method="initMethod3" default-destroy-method="destroyMethod3">
<bean id="beanC" class="org.springframework.beans.factory.xml.InitDestroyBean"/>
</beans>
<beans> <!-- should fall back to outer defaults (initMethod2 and destroyMethod2) -->
<bean id="beanD" class="org.springframework.beans.factory.xml.InitDestroyBean"/>
</beans>
</beans>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- lazy == false (based on default XSD values) -->
<bean id="foo" class="java.lang.Object"/>
<beans default-lazy-init="true">
<!-- lazy == true (explicit default specified) -->
<bean id="bar" class="java.lang.Object"/>
</beans>
<beans default-lazy-init="false">
<!-- lazy == false (explicit default specified) -->
<bean id="baz" class="java.lang.Object"/>
</beans>
<beans default-lazy-init="true">
<!-- lazy == true (explicit default specified) -->
<bean id="biz" class="java.lang.Object"/>
<beans>
<!-- lazy == true (inherit enclosing <beans> defaults -->
<bean id="buz" class="java.lang.Object"/>
</beans>
</beans>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
default-merge="false">
<bean id="abstractTestBean" class="test.beans.TestBean" abstract="true">
<property name="someList">
<list>
<value>alpha</value>
<value>bravo</value>
</list>
</property>
</bean>
<bean id="topLevelConcreteTestBean" parent="abstractTestBean">
<property name="someList">
<list>
<value>charlie</value>
<value>delta</value>
</list>
</property>
</bean>
<beans default-merge="true">
<bean id="firstLevelNestedTestBean" parent="topLevelConcreteTestBean">
<property name="someList">
<list>
<value>echo</value>
<value>foxtrot</value>
</list>
</property>
</bean>
<beans>
<bean id="secondLevelNestedTestBean" parent="firstLevelNestedTestBean">
<property name="someList">
<list>
<value>golf</value>
<value>hotel</value>
</list>
</property>
</bean>
</beans>
</beans>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="foo" class="java.lang.String"/>
<beans profile="dev">
<!-- should override the 'foo' bean above when the 'dev' profile is active -->
<bean name="foo" class="java.lang.Integer">
<constructor-arg value="42"/>
</bean>
<!-- should only be available when the 'dev' profile is active -->
<bean name="devOnlyBean" class="java.lang.Object"/>
</beans>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
profile="dev">
<bean id="foo" class="java.lang.String"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
profile="dev,prod">
<bean id="foo" class="java.lang.String"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="foo" class="java.lang.String"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
profile="prod">
<bean id="foo" class="java.lang.String"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"
profile="unknown">
<bean id="foo" class="java.lang.String"/>
</beans>
#Wed Jul 15 00:01:30 PDT 2009
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
......
......@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<packaging>jar</packaging>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
</parent>
......
#Wed Jul 15 00:01:31 PDT 2009
#Mon Sep 06 21:53:54 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
......
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.3.3.201004202100-CI-R3763-B716]]></pluginVersion>
<pluginVersion><![CDATA[2.5.0.201008272200-CI-R3822-B852]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
......@@ -11,7 +11,6 @@
<config>src/test/java/org/springframework/context/annotation/configuration/SecondLevelSubConfig-context.xml</config>
<config>src/test/java/org/springframework/context/annotation/configuration/ImportXmlWithAopNamespace-context.xml</config>
<config>src/test/java/org/springframework/context/annotation/Spr6602Tests-context.xml</config>
<config>src/test/java/org/springframework/beans/factory/FactoryBeanLookupTests-context.xml</config>
</configs>
<configSets>
</configSets>
......
......@@ -6,12 +6,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<packaging>jar</packaging>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.5.BUILD-SNAPSHOT</version>
<version>3.1.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
......
......@@ -19,6 +19,7 @@ package org.springframework.context;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
......@@ -53,7 +54,7 @@ import org.springframework.core.io.support.ResourcePatternResolver;
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.core.io.ResourceLoader
*/
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
/**
......
......@@ -19,6 +19,8 @@ package org.springframework.context;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* SPI interface to be implemented by most if not all application contexts.
......@@ -31,6 +33,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
* methods should only be used by startup and shutdown code.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 03.11.2003
*/
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle {
......@@ -59,6 +62,11 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
*/
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
/**
* Name of the {@link Environment} bean in the factory.
*/
String ENVIRONMENT_BEAN_NAME = "environment";
/**
* Name of the System properties bean in the factory.
* @see java.lang.System#getProperties()
......@@ -87,6 +95,16 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
*/
void setParent(ApplicationContext parent);
/**
* TODO SPR-7508: document
*/
ConfigurableEnvironment getEnvironment();
/**
* TODO SPR-7508: document
*/
void setEnvironment(ConfigurableEnvironment environment);
/**
* Add a new BeanFactoryPostProcessor that will get applied to the internal
* bean factory of this application context on refresh, before any of the
......@@ -105,7 +123,7 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
* @see org.springframework.context.event.ContextRefreshedEvent
* @see org.springframework.context.event.ContextClosedEvent
*/
void addApplicationListener(ApplicationListener listener);
void addApplicationListener(ApplicationListener<?> listener);
/**
* Load or refresh the persistent representation of the configuration,
......
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context;
import org.springframework.core.env.Environment;
/**
* TODO SPR-7515: document
*
* @author Chris Beams
*/
public interface EnvironmentAware {
void setEnvironment(Environment environment);
}
......@@ -24,6 +24,9 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
/**
* Convenient adapter for programmatic registration of annotated bean classes.
......@@ -31,6 +34,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
* the same resolution of annotations but for explicitly registered classes only.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0
* @see AnnotationConfigApplicationContext#register
*/
......@@ -38,6 +42,8 @@ public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private Environment environment = new DefaultEnvironment();
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
......@@ -61,9 +67,17 @@ public class AnnotatedBeanDefinitionReader {
return this.registry;
}
/**
* Set the Environment to use when registering classes.
* <p>The default is a {@link DefaultEnvironment}.
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* Set the BeanNameGenerator to use for detected bean classes.
* <p>Default is a {@link AnnotationBeanNameGenerator}.
* <p>The default is a {@link AnnotationBeanNameGenerator}.
*/
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());
......@@ -92,8 +106,45 @@ public class AnnotatedBeanDefinitionReader {
registerBean(annotatedClass, null, qualifiers);
}
private boolean hasEligibleProfile(AnnotationMetadata metadata) {
boolean hasEligibleProfile = false;
if (!metadata.hasAnnotation(Profile.class.getName())) {
hasEligibleProfile = true;
} else {
for (String profile : (String[])metadata.getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
if (this.environment.getActiveProfiles().contains(profile)) {
hasEligibleProfile = true;
break;
}
}
}
return hasEligibleProfile;
}
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (!hasEligibleProfile(abd.getMetadata())) {
// TODO SPR-7508: log that this bean is being rejected on profile mismatch
return;
}
/*
if (metadata.hasAnnotation(Profile.class.getName())) {
if (this.environment == null) {
return;
}
Map<String, Object> profileAttribs = metadata.getAnnotationAttributes(Profile.class.getName());
String[] names = (String[]) profileAttribs.get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME);
boolean go=false;
for (String pName : names) {
if (this.environment.getActiveProfiles().contains(pName)) {
go = true;
}
}
if (!go) {
return;
}
}
*/
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
......
......@@ -16,8 +16,11 @@
package org.springframework.context.annotation;
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* Standalone application context, accepting annotated classes as input - in particular
......@@ -46,6 +49,9 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
private final ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this);
{ // TODO: rework this, it's a bit confusing
this.setEnvironment(this.getEnvironment());
}
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
......@@ -75,6 +81,15 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
refresh();
}
/**
* TODO SPR-7508: document
*/
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
/**
* Set the BeanNameGenerator to use for detected bean classes.
......@@ -94,7 +109,6 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
/**
* Register an annotated class to be processed. Allows for programmatically
* building a {@link AnnotationConfigApplicationContext}. Note that
......
......@@ -39,7 +39,7 @@ import org.springframework.util.ClassUtils;
* @author Chris Beams
* @since 2.5
* @see CommonAnnotationBeanPostProcessor
* @see org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
* @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
* @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
......
......@@ -101,7 +101,7 @@ public @interface Bean {
* <p>Note: Only invoked on beans whose lifecycle is under the full control of the
* factory, which is always the case for singletons but not guaranteed
* for any other scope.
* @see {@link org.springframework.context.ConfigurableApplicationContext#close()}
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
String destroyMethod() default "";
......
......@@ -27,6 +27,7 @@ import org.springframework.beans.factory.support.BeanDefinitionDefaults;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.PatternMatchUtils;
......@@ -48,6 +49,7 @@ import org.springframework.util.PatternMatchUtils;
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
* @since 2.5
* @see AnnotationConfigApplicationContext#scan
* @see org.springframework.stereotype.Component
......@@ -87,6 +89,10 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
* {@link org.springframework.context.ApplicationContext} implementations.
* <p>If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a
* {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver}.
* <p>If the the passed-in bean factory also implements {@link EnvironmentCapable} its
* environment will be used by this reader. Otherwise, the reader will initialize and
* use a {@link DefaultEnvironment}. All ApplicationContext implementations are
* EnvironmentCapable, while normal BeanFactory implementations are not.
* @param registry the BeanFactory to load bean definitions into,
* in the form of a BeanDefinitionRegistry
* @param useDefaultFilters whether to include the default filters for the
......@@ -96,6 +102,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
* {@link org.springframework.stereotype.Controller @Controller} stereotype
* annotations.
* @see #setResourceLoader
* @see #setEnvironment
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
super(useDefaultFilters);
......@@ -107,6 +114,11 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
if (this.registry instanceof ResourceLoader) {
setResourceLoader((ResourceLoader) this.registry);
}
// Inherit Environment if possible
if (this.registry instanceof EnvironmentCapable) {
setEnvironment(((EnvironmentCapable) this.registry).getEnvironment());
}
}
......
......@@ -25,11 +25,13 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
......@@ -46,7 +48,6 @@ import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.SystemPropertyUtils;
/**
* A component provider that scans the classpath from a base package. It then
......@@ -59,18 +60,21 @@ import org.springframework.util.SystemPropertyUtils;
* @author Mark Fisher
* @author Juergen Hoeller
* @author Ramnivas Laddad
* @author Chris Beams
* @since 2.5
* @see org.springframework.core.type.classreading.MetadataReaderFactory
* @see org.springframework.core.type.AnnotationMetadata
* @see ScannedGenericBeanDefinition
*/
public class ClassPathScanningCandidateComponentProvider implements ResourceLoaderAware {
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
protected final Log logger = LogFactory.getLog(getClass());
private Environment environment = new DefaultEnvironment();
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
......@@ -110,6 +114,20 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
}
/**
* TODO SPR-7508: document
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* TODO SPR-7508: document
*/
public Environment getEnvironment() {
return this.environment;
}
/**
* Return the ResourceLoader that this component provider uses.
*/
......@@ -261,7 +279,7 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
* @return the pattern specification to be used for package searching
*/
protected String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
return ClassUtils.convertClassNameToResourcePath(environment.resolveRequiredPlaceholders(basePackage));
}
/**
......@@ -278,12 +296,28 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return true;
return hasEligibleProfile(metadataReader);
}
}
return false;
}
private boolean hasEligibleProfile(MetadataReader metadataReader) {
boolean hasEligibleProfile = false;
if (!metadataReader.getAnnotationMetadata().hasAnnotation(Profile.class.getName())) {
hasEligibleProfile = true;
} else {
for (String profile : (String[])metadataReader.getAnnotationMetadata().getAnnotationAttributes(Profile.class.getName()).get(Profile.CANDIDATE_PROFILES_ATTRIB_NAME)) {
if (this.environment.getActiveProfiles().contains(profile)) {
hasEligibleProfile = true;
break;
}
}
}
return hasEligibleProfile;
}
/**
* Determine whether the given bean definition qualifies as candidate.
* <p>The default implementation checks whether the class is concrete
......
/*
* Copyright 2002-2010 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
/**
* Configures component scanning directives for use with {@link Configuration}
* classes. Provides support parallel with Spring XML's
* &lt;context:component-scan&gt; element.
*
* TODO SPR-7508: complete documentation.
*
* @author Chris Beams
* @since 3.1
* @see FilterType
* @see Configuration
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
/** base packages to scan */
String[] value() default {};
Class<?>[] packageOf() default Void.class;
Class<? extends BeanNameGenerator> nameGenerator() default AnnotationBeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
String resourcePattern() default "**/*.class";
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
boolean useDefaultFilters() default true;
IncludeFilter[] includeFilters() default {};
ExcludeFilter[] excludeFilters() default {};
@Retention(RetentionPolicy.SOURCE)
@interface IncludeFilter {
FilterType type() default FilterType.ANNOTATION;
Class<?> value();
}
@Retention(RetentionPolicy.SOURCE)
@interface ExcludeFilter {
FilterType type() default FilterType.ANNOTATION;
Class<?> value();
}
}
......@@ -98,6 +98,7 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
// Delegate bean definition registration to scanner class.
ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);
scanner.setResourceLoader(readerContext.getResourceLoader());
scanner.setEnvironment(parserContext.getDelegate().getEnvironment());
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
......
......@@ -57,6 +57,7 @@ import org.springframework.stereotype.Component;
* @see Bean
* @see ConfigurationClassPostProcessor
* @see AnnotationConfigApplicationContext
* @see org.springframework.context.annotation.Profile
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
......
......@@ -105,7 +105,6 @@ final class ConfigurationClass {
return this.importedResources;
}
public void validate(ProblemReporter problemReporter) {
// An @Bean method may only be overloaded through inheritance. No single
// @Configuration class may declare two @Bean methods with the same name.
......
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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.
......@@ -16,19 +16,39 @@
package org.springframework.context.annotation;
import org.springframework.core.type.filter.AssignableTypeFilter;
/**
* Enumeration of the valid type filters to be added for annotation-driven configuration.
* Enumeration of the type filters that may be used in conjunction with
* {@link ComponentScan @ComponentScan}.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
* @since 2.5
* @see ComponentScan
* @see ComponentScan.IncludeFilter
* @see ComponentScan.ExcludeFilter
* @see org.springframework.core.type.filter.TypeFilter
*/
public enum FilterType {
/**
* Filter candidates marked with a given annotation.
* @see org.springframework.core.type.filter.AnnotationTypeFilter
*/
ANNOTATION,
/**
* Filter candidates assignable to a given type.
* @see AssignableTypeFilter
*/
ASSIGNABLE_TYPE,
ASPECTJ_PATTERN,
REGEX_PATTERN,
/** Filter candidates using a given custom
* {@link org.springframework.core.type.filter.TypeFilter} implementation
*/
CUSTOM
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册