初始化bean的堆栈:

      at org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy$CglibSubclassCreator.instantiate(CglibSubclassingInstantiationStrategy.java:)
at org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection(CglibSubclassingInstantiationStrategy.java:)
at org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection(CglibSubclassingInstantiationStrategy.java:)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory$.getObject(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:)
- locked <0x667> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:)
- locked <0x668> (a java.lang.Object)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:)
at AnnoIoCTest.main(AnnoIoCTest.java:)

spring 初始化bean 的时候会使用一个 initializationStrategy, 默认就是 SimpleInstantiationStrategy, 关键就在于 它的 instantiate方法:

    public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
if(bd.getMethodOverrides().isEmpty()) {
Object var5 = bd.constructorArgumentLock;
Constructor constructorToUse;
synchronized(bd.constructorArgumentLock) {
constructorToUse = (Constructor)bd.resolvedConstructorOrFactoryMethod;
if(constructorToUse == null) {
final Class clazz = bd.getBeanClass();
if(clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
} try {
if(System.getSecurityManager() != null) {
constructorToUse = (Constructor)AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[])null);
}
});
} else {
constructorToUse = clazz.getDeclaredConstructor((Class[])null);
} bd.resolvedConstructorOrFactoryMethod = constructorToUse;
} catch (Throwable var9) {
throw new BeanInstantiationException(clazz, "No default constructor found", var9);
}
}
} return BeanUtils.instantiateClass(constructorToUse, new Object[]);
} else {
return this.instantiateWithMethodInjection(bd, beanName, owner); 如果存在bean 覆盖,那么就 将那个方法注入过来吧!
}
}

这里instantiateWithMethodInjection 具体是由 CglibSubclassingInstantiationStrategy。 它是一个很重要的类。 顾名思义,它主要使用了 cglib 技术。 其中的 instantiate , 正是创建了 一个cglib 代理类,

        public Object instantiate(Constructor<?> ctor, Object... args) {
Class subclass = this.createEnhancedSubclass(this.beanDefinition); // 正是这里, 创建了一个 cglib 子类
Object instance;
if(ctor == null) {
instance = BeanUtils.instantiateClass(subclass);// 实例化它
} else {
try {
Constructor factory = subclass.getConstructor(ctor.getParameterTypes());
instance = factory.newInstance(args);
} catch (Exception var6) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", var6);
}
} Factory factory1 = (Factory)instance;
factory1.setCallbacks(new Callback[]{NoOp.INSTANCE, new CglibSubclassingInstantiationStrategy.LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), new CglibSubclassingInstantiationStrategy.ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;// setCallBack 是给它设置一些拦截器, 以便做些实际的操作。 因为默认的cglib代理类并不会做任何事情。
}

不出所料,  LookupOverrideMethodInterceptor 处理 lookup-method, 而ReplaceOverrideMethodInterceptor 处理replace-method 。

public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
LookupOverride lo = (LookupOverride)this.getBeanDefinition().getMethodOverrides().getOverride(method);
Object[] argsToUse = args.length > ?args:null;
return StringUtils.hasText(lo.getBeanName())?this.owner.getBean(lo.getBeanName(), argsToUse):this.owner.getBean(method.getReturnType(), argsToUse);
}

上面的intercept 方法返回的其实,正是  lookup-method 的bean 属性对应的对象。 而 原bean 的实例, 其实已经变成了 cglib 实现的 原class 的子类了。

获取lookup 方法的堆栈:

at org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy$LookupOverrideMethodInterceptor.intercept(CglibSubclassingInstantiationStrategy.java:283)
at com.baobaotao.Player$$EnhancerBySpringCGLIB$$1caa0626.getDelegete(<generated>:-1)
at com.baobaotao.Player.sayName(Player.java:15)
at AnnoIoCTest.main(AnnoIoCTest.java:15)

replace-method 和   lookup-method 的工作原理是类似的。

    <bean id="player" class="com.baobaotao.Player">
<replaced-method name="getDelegete" replacer="playerLk">
<arg-type match="look">
</arg-type>
</replaced-method>
</bean> <bean id="playerLk" class="com.baobaotao.LkMethodReplacer">
<constructor-arg value="vvv"></constructor-arg>
</bean>

replacer 需要实现 MethodReplacer:

public class LkMethodReplacer implements MethodReplacer {
public String str; public LkMethodReplacer(String str) {
this.str = str;
} public PlayerLk reimplement(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("LkMethodReplacer.reimplement");
return new PlayerLk(str);
}
}

那么  lookup-method & replace-method  用于哪些地方呢?

用于:

单例类调用原型类,默认情况被调用的原形类仍是单例模式(即单例模式覆盖了原型模式),而通过lookup-method属性给单例类注入原型模式类的不同的实例。

他们之间有 什么区别呢?

其实很多时候 使用Autowired 即可, 但是, 使用场景还是有所不同的。  Autowired用于  给一个单例对象注入另一个单例对象。 但是如果想注入另外一个 原型对象。 那么久行不通了! 这个时候就使用  lookup-method 吧!! 

参考:

http://blog.csdn.net/huyangyamin/article/details/52126227

http://blog.csdn.net/u012881904/article/details/51116383 非常详细!

spring 之 lookup-method & replace-method的更多相关文章

  1. .replace(R.id.container, new User()).commit();/The method replace(int, Fragment) in the type FragmentTransaction is not app

    提示错误:The method replace(int, Fragment) in the type FragmentTransaction is not applicable for the arg ...

  2. 错误:The method replace(int, Fragment) in the type FragmentTransaction is not applicable for the arguments (int, MyFragment)

    Fragment newfragment =new MyFragment();fragmentTransaction.replace(R.layout.activity_main,newfragmen ...

  3. Spring 通过工厂方法(Factory Method)来配置bean

    Spring 通过工厂方法(Factory Method)来配置bean 在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. ...

  4. 『重构--改善既有代码的设计』读书笔记----Replace Method with Method Object

    有时候,当你遇到一个大型函数,里面的临时变量和参数多的让你觉得根本无法进行Extract Method.重构中也大力的推荐短小函数的好处,它所带来的解释性,复用性让你收益无穷.但如果你遇到上种情况,你 ...

  5. The method replace(int, Fragment, String) in the type FragmentTransaction is not applicable for the arguments (int, SettingFragment, String)

    The method replace(int, Fragment, String) in the type FragmentTransaction is not applicable for the ...

  6. 重构 改善既有代码的设计 Replace Method with Method Object(以函数对象取代函数)

    你有一个大型函数,其中对局部变量的使用使你无法采用Extract Method. 将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段.然后你可以在同一个对象中将这个大型函数分解为多个小型 ...

  7. 关于.ToList(): LINQ to Entities does not recognize the method ‘xxx’ method, and this method cannot be translated into a store expression.

    LINQ to Entities works by translating LINQ queries to SQL queries, then executing the resulting quer ...

  8. org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method service() cannot be found on com.my.blog.springboot.thymeleaf.util.MethodTest type

    前言 本文中提到的解决方案,源码地址在:springboot-thymeleaf,希望可以帮你解决问题. 至于为什么已经写了一篇文章thymeleaf模板引擎调用java类中的方法,又多此一举的单独整 ...

  9. Python OOP(2)-static method,class method and instance method

    静态方法(Static Method): 一种简单函数,符合以下要求: 1.嵌套在类中. 2.没有self参数. 特点: 1.类调用.实例调用,静态方法都不会接受自动的self参数. 2.会记录所有实 ...

  10. 1.spring.net Look-up Method 查找方法的注入(方法是抽象的需要spring.net注入)

    .为什么需要查找方法的注入 当Object依赖另一个生命周期不同的Object,尤其是当singleton依赖一个non-singleton时,常会遇到不少问题,Lookup Method Injec ...

随机推荐

  1. JAVA面向对象编程之购物车界面的设计与功能的实现

    1.小组成员及分工 小组成员 负责工作 兰泽祥 负责总体界面.Git代码库 吴修恩 负责MVC模式.类名包名的规范化 2.Git 仓库地址 仓库地址:https://gitee.com/lanzexi ...

  2. Java 内存溢出(java.lang.OutOfMemoryError)情况总结

    最近做一个项目,因为分了十几个模块,但是每次在Eclipse中启动Tomcat必须加载四五个模块,这样出现了 java.lang.OutOfMemoryError 原因是Eclipse中Tomcat设 ...

  3. R语言——实验5-聚类分析

    针对课件中的例子自己实现k-means算法 调用R语言自带kmeans()对给定数据集表示的文档进行聚类. 给定数据集: a)         数据代表的是文本信息. b)        第一行代表词 ...

  4. CSS自定义滚动条样式

    原文地址:http://www.qianduan.net/css-custom-scroll-bar-style/ 相信很多人都遇到过在设计中自定义滚动条样式的情景,之前我都是努力说服设计师接受浏览器 ...

  5. C语言强化——学生管理系统

    系统模块设计 a.预处理模块 系统在启动时会根据配置文件里的内容去相应文件里去加载账户信息和学生信息. b.登陆模块 输入用户名和密码,输密码的时候用"*" 代表用户当前输入的内容 ...

  6. Aspose.Word 输出表格后空格字符丢失的解决方法

    将datatable输出到word,执行如下代码. doc.MailMerge.ExecuteWithRegions(outDt); 执行完后发现第一列含前缀空格的字段值,空格字符被自动清除了. 解决 ...

  7. 删除win7任务栏通知区域图标的方法

    大家都知道程序运行后会在任务栏的通知区域显示表明正在运行,但是有很多失效的图标也会在此显示,那么怎么样删除那些没用的图标呢? 1.在开始运行里输入:regedit进入注册表编辑器 2.进入注册表编辑器 ...

  8. CRM 权限内可查看的记录数

    CREATE FUNCTION dbo.fn_GetFilteredIdsSqlString ( ) , ) , ) ) RETURNS NVARCHAR(max) AS BEGIN ) SET @s ...

  9. c#线程间传递参数

    线程操作主要用到Thread类,他是定义在System.Threading.dll下.使用时需要添加这一个引用.该类提供给我们四个重载的构造函数(以下引自msdn).        Thread (P ...

  10. selenium在scrapy中的应用

    引入 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现 ...