– Start
点击此处观看本系列配套视频。
当你想把短生命周期的对象(如: prototype)注入到长生命周期的对象(如:singleton)时需要特别注意,Spring 提供了如下的解决办法。
使用代理 aop:scoped-proxy/
package shangbo.spring.example29;
public interface MessageService {
String getMessage();
}
package shangbo.spring.example29;
public class MessageServiceImpl implements MessageService {
private int times = 0;
public String getMessage() {
times++;
return "Hello World-" + times;
}
}
package shangbo.spring.example29;
public class MessagePrinter {
final private MessageService service;
public MessagePrinter(MessageService service) {
this.service = service;
}
public void printMessage() {
System.out.println(this.service.getMessage());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--
注意messageService对象是 prototype
<aop:scoped-proxy/> 指示容器生成代理对象
-->
<bean id="messageService" class="shangbo.spring.example29.MessageServiceImpl" scope="prototype">
<aop:scoped-proxy/>
</bean>
<!--
MessagePrinter 是 singleton 对象
-->
<bean class="shangbo.spring.example29.MessagePrinter">
<constructor-arg ref="messageService"/>
</bean>
</beans>
package shangbo.spring.example29;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 实例化 Spring IoC 容器
ApplicationContext context = new ClassPathXmlApplicationContext("example.xml", MessagePrinter.class);
// 从容器中获得 MessagePrinter 的实例
MessagePrinter printer1 = context.getBean(MessagePrinter.class);
printer1.printMessage();
// 再次在容器中获得 MessagePrinter 的实例
MessagePrinter printer2 = context.getBean(MessagePrinter.class);
printer2.printMessage();
}
}
使用 lookup 方法
package shangbo.spring.example30;
public interface MessageService {
String getMessage();
}
package shangbo.spring.example30;
public class MessageServiceImpl implements MessageService {
private int times = 0;
public String getMessage() {
times++;
return "Hello World-" + times;
}
}
package shangbo.spring.example30;
public abstract class MessagePrinter {
public void printMessage() {
MessageService service = createMessageService();
System.out.println(service.getMessage());
}
// 注意,这是传说中的 lookup 方法
protected abstract MessageService createMessageService();
}
<?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.xsd">
<bean id="messageService" class="shangbo.spring.example30.MessageServiceImpl" scope="prototype"/>
<!--
注入 lookup 方法
-->
<bean class="shangbo.spring.example30.MessagePrinter">
<lookup-method name="createMessageService" bean="messageService"/>
</bean>
</beans>
package shangbo.spring.example30;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import shangbo.spring.example29.MessagePrinter;
public class App {
public static void main(String[] args) {
// 实例化 Spring IoC 容器
ApplicationContext context = new ClassPathXmlApplicationContext("example.xml", MessagePrinter.class);
// 从容器中获得 MessagePrinter 的实例
MessagePrinter printer1 = context.getBean(MessagePrinter.class);
printer1.printMessage();
// 再次在容器中获得 MessagePrinter 的实例
MessagePrinter printer2 = context.getBean(MessagePrinter.class);
printer2.printMessage();
}
}
Spring 还提供了其他方法,如注入 ,或实现 ApplicationContextAware 接口,但是它们需要继承 Spring 的接口,与 Spring 耦合在一起,不推荐使用。
– 更多参见:Spring Framework 精萃
– 声 明:转载请注明出处
– Last Updated on 2017-05-23
– Written by ShangBo on 2017-05-23
– End