Spring基本使用(元素lookup-method使用)

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 的实例。代码示例如下:
  1. 定义一个接口
package com.willhonor.test.useApplicationContext3LookupOrReplaceMethods;

public interface FFruit {
	void say();
}
  1. 接口 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()}));
	}
}
  1. 定义另一个类(用作上述中的 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() {
		// 每次从 bean工厂获取一个 apple
		return (FFruit) context.getBean("apple");
	}
	// 保存 applicationContext 引用
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.context = applicationContext;
	}
}
  1. 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>
  1. 测试代码如下
package com.willhonor.test.useApplicationContext3LookupOrReplaceMethods;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 元素 lookup-method 使用
 * @author jokee
 *
 */
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();
	}
}
  1. 执行结果如下(可见单例 bean persona 连续执行了 4 次,每次都获取一个新的 apple)
...
#此处省略 spring 日志打印
...
fapple, 苹果[226170135]
fapple, 苹果[381707837]
fapple, 苹果[589446616]
fapple, 苹果[1321640594]
2. 使用元素 lookup-method 实现
  • 使用 lookup-method 来实现前面示例的效果,仅仅修改 bean A 以及 spring 配置文件即可,其它部分保持不变。
  1. 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("没有水果吃");
		}
	}
	/** 方法返回 null,别慌,IOC 容器会帮我们覆盖这个方法 */
	public FFruit getAFFruit() {
		return null;
	}
}
  1. 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">
		<!-- 告诉容器覆盖 getFFruit 方法,并期望新的方法返回 bean apple 的实例, -->
		<!-- 因为 bean apple 定义为非单例,所以新的方法每次返回一个新的 apple -->
		<lookup-method name="getAFFruit" bean="apple"/>
	</bean>
	
	<bean id="apple" singleton="false"
		class="com.willhonor.test.useApplicationContext3LookupOrReplaceMethods.FApple"></bean>
</beans>
  1. 再次执行测试,执行结果达到预期
...
#此处省略 spring 日志打印
...
fapple, 苹果[710714889]
fapple, 苹果[551734240]
fapple, 苹果[1757293506]
fapple, 苹果[687780858]
3. 其它
  1. 我使用的 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>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
		<!-- <dependency> -->
		<!-- <groupId>org.springframework</groupId> -->
		<!-- <artifactId>spring-core</artifactId> -->
		<!-- <version>1.2.6</version> -->
		<!-- </dependency> -->
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>1.2.6</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>1.2.6</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>1.2.6</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>1.2.6</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.3</version>
			<!-- <scope>provided</scope> -->
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
		<dependency>
			<groupId>org.mariadb.jdbc</groupId>
			<artifactId>mariadb-java-client</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/junit/junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<!-- <scope>test</scope> -->
		</dependency>
		<!-- https://mvnrepository.com/artifact/cglib/cglib -->
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>2.1_3</version>
		</dependency>
	</dependencies>
</project>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值