- 浏览: 434523 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
pulsar_lxl:
请注明转载原文:http://hllvm.group.itey ...
JVM研究 -
goycejin:
感谢楼主,我也要及笔记了,这记性
Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.8.1:jar -
lianglong2000:
我理解是 java -server 类名 是运行的jdk中的j ...
jdk,jre你真的懂吗? -
yanqlv:
有个问题,既然windows目录(Windows/system ...
jdk,jre你真的懂吗? -
yanqlv:
系统化的描述也挺重要,架构模式>设计模式,架构模式≈设计 ...
MVC是设计模式么?是框架么?
Spring使用CGLIB的动态字节码增强功能,所以,必须要加入CGLIB包
当Bean依赖另一个生命周期不同的bean,尤其是当singleton依赖一个non-singleton时,常会遇到不少问题,Lookup Method Injection正是对付这些问题而出现的,在上述情况中,setter和构造注入都会导致singleton去维护一个non-singleton bean的单个实例,某些情况下,我们希望让singleton bean每次要求获得bean时候都返回一个non-singleton bean的新实例
当一个singleton bean A 在每次方法调用的时候都需要一个non-singleton bean B,此时就会产生这样一个问题,因为A为singleton,所以容器只会创建一次A,那么也只有一次机会来创建A的属性,Bean B也只能被初始化一次,但是我们调用每个方法的时候又都需要一个新的B的实例。通常的时候我们只要new一个就可以,但在Spring中这不符合整体性的设计,这样就有了方法注入。
让我们开始一个简单的测试。
在你的工程的根目录中分别建立一个src,classes,lib文件夹。此次我们将采用Ant来进行部署。
在src中建立Random.java,HelloRandom.java,HelloAbstract.java,Test.java。代码如下。
Random.java这是一个可以产生随机数的类,很简单。
package com.testspring.basic.lookup;
public class Random {
private int num = (int)(100*Math.random());
public void printRandom(){
System.out.println("随机数是"+num);
}
}
HelloRandom.java一个代理接口。
package com.testspring.basic.lookup;
public interface HelloRandom {
public Random getRandom();
public abstract Random createRandom(); //这个方法最为重要,是方法注入的关键
}
HelloAbstract.java
package com.testspring.basic.lookup;
public abstract class HelloAbstract implements HelloRandom{
private Random random;
public void setRandom(Random random){
this.random = random;
}
public Random getRandom(){
return this.random;
}
public abstract Random createRandom();
}
Test.java用于测试
package com.testspring;
import org.springframework.context.ApplicationContext;
import com.testspring.basic.lookup.*;
public class Test {
public static void main(String[] args) {
try{
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
HelloRandom helloRandom = (HelloRandom)context.getBean("helloRandom");
System.out.println("下面两个实例没有采用方法注入");
Random r1 = helloRandom.getRandom();
Random r2 = helloRandom.getRandom();
System.out.println("Random 的两个实例是否指向同一个引用:" + (r1 == r2));
r1.printRandom();
r2.printRandom();
System.out.println();
System.out.println("下面两个实例采用方法注入");
Random r3 = helloRandom.createRandom();
Random r4 = helloRandom.createRandom();
System.out.println("Random 的两个实例是否指向同一个引用:" + (r3 == r4));
r3.printRandom();
r4.printRandom();
}catch(Exception e){
e.printStackTrace();
}
}
}
在src中建立一个bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 方法注入-->
<bean id="myRandom" class="com.testspring.basic.lookup.Random" scope="prototype" />
<bean id="helloRandom" class="com.testspring.basic.lookup.HelloAbstract">
<lookup-method name="createRandom" bean="myRandom"/>
<property name="random">
<ref local="myRandom" />
</property>
</bean>
</beans>
在根目录中建立一个build.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project name="MySpring" default="run" basedir=".">
<!-- 全局变量的定义 -->
<property name="src.dir" value="src" /> <!-- 源文件位置 -->
<property name="classes.dir" value="classes" /> <!-- class文件位置 -->
<property name="lib.dir" value="lib" /> <!-- 引用的jar文件位置 -->
<!--当前工程环境变量-->
<path id="Project-Classpath">
<pathelement path="${classes.dir}"/>
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
</path>
<!--编译-->
<target name="compile" depends="clean">
<javac srcdir="${src.dir}" destdir="${classes.dir}">
<classpath refid="Project-Classpath" />
</javac>
</target>
<!--复制除了java文件以外的文件-->
<target name="copy-resources" depends="compile">
<copy todir="${classes.dir}">
<fileset dir="${src.dir}">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<!--运行-->
<target name="run">
<java fork="true" classname="com.testspring.Test">
<classpath refid="Project-Classpath" />
</java>
</target>
</project>
将spring.jar,cglib-nodep-2.1_3.jar放入lib中。
运行build命令就可以看到我们的结果了
----------------------------------------------------------------------------------------------
下面两个实例没有采用方法注入
Random 的两个实例是否指向同一个引用:true
随机数是99
随机数是99
下面两个实例采用方法注入
Random 的两个实例是否指向同一个引用:false
随机数是98
随机数是17
注意事项:
1.应用场合:一个singleton的Bean需要引用一个prototype的Bean; 一个无状态的Bean需要引用一个有状态的Bean; ... ; 等等情景下.
2.假定你有三个singleton,公用一个依赖,希望每个singleton有自己的实例依赖,所以将依赖设置成singleton,但
实际上每个singleton在其生命周期中使用协作着的同一个实例足以,这种情况下,setter是最好的选择,使用方
法查找注入会增加不必要的开销
3.我们也可以使用实现BeanFactoryAware的方式代替Lookup Method Injection
public void setBeanFactory(Beanfactory factory){
this.factory=factory;
}
public Random createRandom(){
return (Random)factory.getBean("myRandom");
}
使用上述方法在效率上和使用本例的方法,相差无几(100000次差别在几毫秒),所以,建议使用本里的方法,减少和spring api的耦合
4.尽管可以不把查找方法定义成abstract,但还是建议这样做,可以防止不小心忘了配置查找方法而留一个空方法在代码中
5. 记住在任何时候只要定义了一个Bean的Lookup方法,那么这个Bean的实例将是一个CGLIB动态生成的实例而不是原来类的实例。
6.Spring允许在一个Bean中定义多个Lookup方法。
7.Spring还允许Lookup方法中定义的方法带有参数,但是Sping不会处理这些参数。
8.Spring对Lookup方法也存在一些限制:
方法不能是private的,但可以是protected的。
方法不能是静态的。
当Bean依赖另一个生命周期不同的bean,尤其是当singleton依赖一个non-singleton时,常会遇到不少问题,Lookup Method Injection正是对付这些问题而出现的,在上述情况中,setter和构造注入都会导致singleton去维护一个non-singleton bean的单个实例,某些情况下,我们希望让singleton bean每次要求获得bean时候都返回一个non-singleton bean的新实例
当一个singleton bean A 在每次方法调用的时候都需要一个non-singleton bean B,此时就会产生这样一个问题,因为A为singleton,所以容器只会创建一次A,那么也只有一次机会来创建A的属性,Bean B也只能被初始化一次,但是我们调用每个方法的时候又都需要一个新的B的实例。通常的时候我们只要new一个就可以,但在Spring中这不符合整体性的设计,这样就有了方法注入。
让我们开始一个简单的测试。
在你的工程的根目录中分别建立一个src,classes,lib文件夹。此次我们将采用Ant来进行部署。
在src中建立Random.java,HelloRandom.java,HelloAbstract.java,Test.java。代码如下。
Random.java这是一个可以产生随机数的类,很简单。
package com.testspring.basic.lookup;
public class Random {
private int num = (int)(100*Math.random());
public void printRandom(){
System.out.println("随机数是"+num);
}
}
HelloRandom.java一个代理接口。
package com.testspring.basic.lookup;
public interface HelloRandom {
public Random getRandom();
public abstract Random createRandom(); //这个方法最为重要,是方法注入的关键
}
HelloAbstract.java
package com.testspring.basic.lookup;
public abstract class HelloAbstract implements HelloRandom{
private Random random;
public void setRandom(Random random){
this.random = random;
}
public Random getRandom(){
return this.random;
}
public abstract Random createRandom();
}
Test.java用于测试
package com.testspring;
import org.springframework.context.ApplicationContext;
import com.testspring.basic.lookup.*;
public class Test {
public static void main(String[] args) {
try{
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
HelloRandom helloRandom = (HelloRandom)context.getBean("helloRandom");
System.out.println("下面两个实例没有采用方法注入");
Random r1 = helloRandom.getRandom();
Random r2 = helloRandom.getRandom();
System.out.println("Random 的两个实例是否指向同一个引用:" + (r1 == r2));
r1.printRandom();
r2.printRandom();
System.out.println();
System.out.println("下面两个实例采用方法注入");
Random r3 = helloRandom.createRandom();
Random r4 = helloRandom.createRandom();
System.out.println("Random 的两个实例是否指向同一个引用:" + (r3 == r4));
r3.printRandom();
r4.printRandom();
}catch(Exception e){
e.printStackTrace();
}
}
}
在src中建立一个bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 方法注入-->
<bean id="myRandom" class="com.testspring.basic.lookup.Random" scope="prototype" />
<bean id="helloRandom" class="com.testspring.basic.lookup.HelloAbstract">
<lookup-method name="createRandom" bean="myRandom"/>
<property name="random">
<ref local="myRandom" />
</property>
</bean>
</beans>
在根目录中建立一个build.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project name="MySpring" default="run" basedir=".">
<!-- 全局变量的定义 -->
<property name="src.dir" value="src" /> <!-- 源文件位置 -->
<property name="classes.dir" value="classes" /> <!-- class文件位置 -->
<property name="lib.dir" value="lib" /> <!-- 引用的jar文件位置 -->
<!--当前工程环境变量-->
<path id="Project-Classpath">
<pathelement path="${classes.dir}"/>
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
</path>
<!--编译-->
<target name="compile" depends="clean">
<javac srcdir="${src.dir}" destdir="${classes.dir}">
<classpath refid="Project-Classpath" />
</javac>
</target>
<!--复制除了java文件以外的文件-->
<target name="copy-resources" depends="compile">
<copy todir="${classes.dir}">
<fileset dir="${src.dir}">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<!--运行-->
<target name="run">
<java fork="true" classname="com.testspring.Test">
<classpath refid="Project-Classpath" />
</java>
</target>
</project>
将spring.jar,cglib-nodep-2.1_3.jar放入lib中。
运行build命令就可以看到我们的结果了
----------------------------------------------------------------------------------------------
下面两个实例没有采用方法注入
Random 的两个实例是否指向同一个引用:true
随机数是99
随机数是99
下面两个实例采用方法注入
Random 的两个实例是否指向同一个引用:false
随机数是98
随机数是17
注意事项:
1.应用场合:一个singleton的Bean需要引用一个prototype的Bean; 一个无状态的Bean需要引用一个有状态的Bean; ... ; 等等情景下.
2.假定你有三个singleton,公用一个依赖,希望每个singleton有自己的实例依赖,所以将依赖设置成singleton,但
实际上每个singleton在其生命周期中使用协作着的同一个实例足以,这种情况下,setter是最好的选择,使用方
法查找注入会增加不必要的开销
3.我们也可以使用实现BeanFactoryAware的方式代替Lookup Method Injection
public void setBeanFactory(Beanfactory factory){
this.factory=factory;
}
public Random createRandom(){
return (Random)factory.getBean("myRandom");
}
使用上述方法在效率上和使用本例的方法,相差无几(100000次差别在几毫秒),所以,建议使用本里的方法,减少和spring api的耦合
4.尽管可以不把查找方法定义成abstract,但还是建议这样做,可以防止不小心忘了配置查找方法而留一个空方法在代码中
5. 记住在任何时候只要定义了一个Bean的Lookup方法,那么这个Bean的实例将是一个CGLIB动态生成的实例而不是原来类的实例。
6.Spring允许在一个Bean中定义多个Lookup方法。
7.Spring还允许Lookup方法中定义的方法带有参数,但是Sping不会处理这些参数。
8.Spring对Lookup方法也存在一些限制:
方法不能是private的,但可以是protected的。
方法不能是静态的。
发表评论
-
Java线程池使用说明
2015-05-12 23:34 1257一简介 线程的使用在java中占有极其重要的地位 ... -
Long == 操作符 的陷阱
2015-02-25 10:38 869当两个对象进行比较的时候,我们应该使用equals方法,但是 ... -
java中只有值传递,没有引用传递
2013-08-24 14:29 1459一、首先来明确一下"值传递"和&quo ... -
java vs javaw vs javaws
2013-08-12 22:54 1487reference:http://javapapers.co ... -
java类的初始化顺序
2013-07-17 23:14 806(1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序 ... -
java泛型
2013-07-04 11:43 1101泛型是Java SE 1.5的新特性,泛型的本质是参数化类 ... -
JVM分代垃圾回收详述
2013-07-03 20:15 907虚拟机中的共划分为三 ... -
JSP 9 大内置对象详解
2013-06-24 23:15 1121内置对象特点:1. 由JSP规范提供,不用编写者实例化2. ... -
什么是J2EE
2013-05-20 19:36 1296J2EE英文全称Java 2 Platform Enterpr ... -
transient Volatile ThreadLocal
2013-04-29 16:05 1270Java的serialization提供了 ... -
java 过滤器 Filter
2012-10-11 14:43 1506Servlet 过滤器是可插入 ... -
java xml解析
2012-08-04 17:11 1751随着XML越来越广泛地被 ... -
Tomcat Web项目中文乱码问题解决方案
2012-07-30 16:58 2875Tomcat常见乱码解决方案:(建议按顺序来看,逐个排除) 1 ... -
list的remove问题
2012-07-17 12:45 17831、增强的for循环里面不 ... -
java方法覆盖的原则
2012-06-06 22:50 1833什么是方法覆盖 如果在子类中定义的一个方法,其名称、返回类型 ... -
继承中的构造方法及覆盖与隐藏
2012-06-06 22:27 2233继承中的构造方法 一、 ... -
java虚拟机内存原型
2012-05-14 17:21 1074寄存器:我们在程序中无法控制 栈:存放基本类型的数据和对象的引 ... -
jdk,jre你真的懂吗?
2012-05-07 11:01 24183关于jdk和jre 大家肯定 ... -
java注解
2012-04-24 16:56 1510Java注解 一、什么是java注解 注 ... -
java
2012-03-16 19:50 8920. 构造方法不能被继承! 1. ...
相关推荐
在Spring框架中,Lookup方法注入是一种特殊的依赖注入方式,它允许Spring容器动态替换bean中的某个方法,以便在运行时返回不同实例。这种方法主要用于处理单例bean依赖非单例bean的情况,确保每次调用都能获得一个新...
在上面的示例中,我们使用 lookup-method 标签来注入 getAuthor() 方法,该方法将返回一个新的 Author Bean 的实例。 四、单元测试 为了验证上述实现,我们可以编写单元测试来测试该实现。例如,我们可以编写以下...
Spring系列第12篇:lazy-init:bean延迟初始化Spring系列第13篇:使用继承简化bean配置(abstract & parent)Spring系列第14篇:lookup-method和replaced-method比较陌生,怎么玩的?Spring系列第15篇:代理详解(Java...
- Spring提供了对Bean生命周期的精细控制,如初始化方法(init-method)和销毁方法(destroy-method)。 4. **自动装配(Autowiring)** - 自动装配是Spring框架的一个特性,允许容器自动将依赖项匹配到相应的...
在Spring框架中,如果你希望一个类的实例在所有属性注入完成后自动执行某些特定的方法,你可以利用Spring的初始化回调机制。这个机制允许你在对象完全构造并准备好执行业务逻辑时执行一些自定义的操作。以下是对这个...
在`<bean>`元素中,`lookup-method`和`replaced-method`属性的引入,使得在运行时动态查找或替换bean的方法成为可能,这是对AOP(面向切面编程)的一种补充,提供了更细粒度的控制。 除此之外,`<util>`命名空间在...
- **Template Method模式**:理解Spring中的模板方法模式如何简化代码结构。 推荐阅读《Expert one-on-one J2EE Design and Development》的第四章,该章节不仅适合Spring初学者,也是Java开发者必读的经典内容。 ...
5. **Spring配置**:在Spring的配置文件中,可以使用`<bean>`标签定义RMI服务,并使用`<lookup-method>`标签来查找并注入远程对象。 ```xml <bean id="myServiceExporter" class="org.springframework.remoting...
2. 使用方法注入(lookup-method),让容器在运行时重写bean的方法,返回其他bean的新实例。 Spring还提供了定制bean生命周期行为的机制。例如,可以在bean初始化完成后执行特定操作: 1. 使用`init-method`属性,...
Spring 框架是Java开发中的一个核心组件,它提供了依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)等特性,极大地简化了企业级应用的开发工作。Spring配置文件是Spring...
Spring框架作为Java领域中最为广泛使用的依赖注入(Dependency Injection, DI)容器之一,其强大的功能不仅体现在对复杂系统的管理上,还包括了许多高级特性,如静态实例化。本文将深入探讨Spring中的静态实例化概念...
10. `<bean>`的`init-method`和`destroy-method`属性:指定bean初始化和销毁时调用的方法。 Spring 3.0-xsd压缩包可能包含了Spring的核心配置XSD、AOP配置XSD、数据源配置XSD等多个文件,这些文件一起构成了Spring ...
lookup-method 可以用来注入 Bean,避免了硬编码的依赖关系。 7. 使用 factory-method 来实例化 Bean factory-method 可以用来实例化 Bean,提供了更多的灵活性。 8. 使用 depends-on 来指定 Bean 的依赖关系 ...
在IT行业中,Spring框架是Java领域最常用的轻量级应用框架之一,而RMI(Remote Method Invocation)则是Java提供的一种远程方法调用机制,用于构建分布式应用程序。将Spring与RMI结合,可以实现非本地部署的服务,...
Java Spring RMI(Remote Method Invocation)是Java平台上用于构建分布式应用程序的一种技术,它允许Java对象在不同的JVM(Java Virtual Machine)之间进行交互。Spring框架提供了对RMI的支持,简化了RMI的配置和...
这段配置查找 JNDI 名称为 `java:comp/env/jdbc/myDS` 的数据源,并将其引用作为 `dataSource` 注入到其他 bean 中。 #### Spring Annotations Spring 2.5 引入了丰富的注解集,这些注解有助于减少 XML 配置的数量...
Spring框架是Java开发中广泛应用的轻量级框架,它提供了丰富的功能来简化应用程序的构建,包括依赖注入、AOP(面向切面编程)以及多种集成技术。RMI(Remote Method Invocation,远程方法调用)是Java平台上的一个...