0.0
可以使用 元素 lookup-method 来取代 ApplicationContextAware 接口 ,避免应用代码直接和和 Spring 代码耦合在一起 注意:元素 lookup-method 会 override 覆盖指定名称的所有同名方法,如果想要覆盖指定的 overload 重载方法,可是使用元素 replaced-method 替代。
1. 使用 ApplicationContextAware 接口实现
假设对单例 bean A 中某个方法 method-a 的每次调用,都需要获取一个新的 bean B 实例。这种情景中,可以让 bean A 实现 ApplicationContextAware 接口,从而可以在 bean A 中访问 bean 工厂,再从 bean 工厂每次获取一个新的 bean B 的实例。代码示例如下:
定义一个接口
package com. willhonor. test. useApplicationContext3LookupOrReplaceMethods;
public interface FFruit {
void say ( ) ;
}
接口 FFruit 的一个具体实现类(用作上述中的 bean B)
package com. willhonor. test. useApplicationContext3LookupOrReplaceMethods;
public class FApple implements FFruit {
public void say ( ) {
System. out. println ( String. format ( "fapple, 苹果[%d]" , new Object [ ] { this . hashCode ( ) } ) ) ;
}
}
定义另一个类(用作上述中的 bean A),该类实现了 ApplicationContextAware 接口
package com. willhonor. test. useApplicationContext3LookupOrReplaceMethods;
import org. springframework. beans. BeansException;
import org. springframework. context. ApplicationContext;
import org. springframework. context. ApplicationContextAware;
public class PersonA_use_lookup_method implements ApplicationContextAware {
private ApplicationContext context;
public void eatFruit ( ) {
FFruit fruit = getAFFruit ( ) ;
if ( fruit != null) {
fruit. say ( ) ;
} else {
System. out. println ( "没有水果吃" ) ;
}
}
public FFruit getAFFruit ( ) {
return ( FFruit) context. getBean ( "apple" ) ;
}
public void setApplicationContext ( ApplicationContext applicationContext) throws BeansException {
this . context = applicationContext;
}
}
spring 配置文件如下(定义了一个单例 bean 即 persona 作为上述场景中的 bean A,和一个非单例 bean 即 apple 作为上述场景中的 bean B)
< ? xml version= "1.0" encoding= "UTF-8" ? >
< ! DOCTYPE beans SYSTEM "spring-beans.dtd" >
< beans>
< bean id= "persona" singleton= "true"
class = "com.willhonor.test.useApplicationContext3LookupOrReplaceMethods.PersonA_use_lookup_method" >
< / bean>
< ! -- 非单例,以便每次都能获取一个新的 apple -- >
< bean id= "apple" singleton= "false"
class = "com.willhonor.test.useApplicationContext3LookupOrReplaceMethods.FApple" > < / bean>
< / beans>
测试代码如下
package com. willhonor. test. useApplicationContext3LookupOrReplaceMethods;
import org. junit. Test;
import org. springframework. context. support. ClassPathXmlApplicationContext;
public class Test_Test_1 {
@Test
public void test_use_lookup_method ( ) throws Exception {
String pathA = "com/willhonor/test/configs/application.d.xml" ;
String[ ] path = new String [ ] { pathA} ;
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ( path) ;
PersonA_use_lookup_method persona =
( PersonA_use_lookup_method) context. getBean ( "persona" ) ;
persona. eatFruit ( ) ;
persona. eatFruit ( ) ;
persona. eatFruit ( ) ;
persona. eatFruit ( ) ;
}
}
执行结果如下(可见单例 bean persona 连续执行了 4 次,每次都获取一个新的 apple)
.. .
.. .
fapple, 苹果[ 226170135]
fapple, 苹果[ 381707837]
fapple, 苹果[ 589446616]
fapple, 苹果[ 1321640594]
2. 使用元素 lookup-method 实现
使用 lookup-method 来实现前面示例的效果,仅仅修改 bean A 以及 spring 配置文件即可,其它部分保持不变。
bean A 修改如下(不再需要实现 ApplicationContextAware 接口)
package com. willhonor. test. useApplicationContext3LookupOrReplaceMethods;
import org. springframework. beans. BeansException;
import org. springframework. context. ApplicationContext;
public class PersonA_use_lookup_method {
public void eatFruit ( ) {
FFruit fruit = getAFFruit ( ) ;
if ( fruit != null) {
fruit. say ( ) ;
} else {
System. out. println ( "没有水果吃" ) ;
}
}
public FFruit getAFFruit ( ) {
return null;
}
}
spring 配置文件修改如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans SYSTEM "spring-beans.dtd">
< beans>
< bean id = " persona" singleton = " true"
class = " com.willhonor.test.useApplicationContext3LookupOrReplaceMethods.PersonA_use_lookup_method" >
< lookup-method name = " getAFFruit" bean = " apple" />
</ bean>
< bean id = " apple" singleton = " false"
class = " com.willhonor.test.useApplicationContext3LookupOrReplaceMethods.FApple" > </ bean>
</ beans>
再次执行测试,执行结果达到预期
.. .
.. .
fapple, 苹果[ 710714889]
fapple, 苹果[ 551734240]
fapple, 苹果[ 1757293506]
fapple, 苹果[ 687780858]
3. 其它
我使用的 Maven 文件配置如下(虽然我测试使用的 spring 版本是 1.2.6,这是 2005 年发布的版本,但是对比 1.2.6 版本的 spring-beans.dtd 和最新的 spring 5 的 spring-beans-2.0.dtd,会发现这两者几乎保持一致,可见 spring 的向后兼容做的很好。)
< project xmlns = " http://maven.apache.org/POM/4.0.0"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= " http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0.0</ modelVersion>
< parent>
< groupId> com.willhonor</ groupId>
< artifactId> todos</ artifactId>
< version> 0.0.1-SNAPSHOT</ version>
</ parent>
< artifactId> spring-1.2.6</ artifactId>
< dependencies>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-context</ artifactId>
< version> 1.2.6</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> 1.2.6</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-jdbc</ artifactId>
< version> 1.2.6</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-aop</ artifactId>
< version> 1.2.6</ version>
</ dependency>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> servlet-api</ artifactId>
< version> 2.3</ version>
</ dependency>
< dependency>
< groupId> org.mariadb.jdbc</ groupId>
< artifactId> mariadb-java-client</ artifactId>
< version> 2.3.0</ version>
</ dependency>
< dependency>
< groupId> junit</ groupId>
< artifactId> junit</ artifactId>
< version> 4.12</ version>
</ dependency>
< dependency>
< groupId> cglib</ groupId>
< artifactId> cglib</ artifactId>
< version> 2.1_3</ version>
</ dependency>
</ dependencies>
</ project>