初始化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. Maven Docker部署

    镜像构建方式 docker-maven-plugin插件构建docker镜像有两种方式: 1. 指定参数,由docker-maven-plugin插件根据这些参数来制作镜像: 2. 指定Dockerf ...

  2. Ntfs 下的链接符号创建

    熟悉过 Unix/Linux 都应该知道,Unix/Linux 用 ln 建立硬链接,ln -s 建立软链接(符号链接). 硬链接和符号链接的区别 Ntfs下的也有链接符: 内置命令:mklink   ...

  3. 黄聪: $(document).click() 在iphone上不触发事件解决办法

    解决方案:加上 touchstart 事件 $(document).on(“click touchstart”, “.name”, function() { alert(“name”); });  

  4. 黄聪:wordpress如何获取访问的网站的cookie值

    $head = wp_get_http_headers( $word_url ); $cookie = $head['set-cookie']; $cookie = substr( $cookie, ...

  5. Centos7 在 Xshell里 vim的配置

    Centos里的VI只默认安装了vim-minimal-7.x.所以无论是输入vi或者vim查看文件,syntax功能都无法正常启用.因此需要用yum安装另外两个组件:vim-common-7.x和v ...

  6. 安装包制作工具 SetupFactory 详解

    Setup Factory 是一个强大的安装程序制作工具.提供了安装制作向导界面,即使你对安装制作不了解,也可以生成专业性质的安装程序.可建立快捷方式,也可直接在 Windows 系统的注册表加入内容 ...

  7. [转][MVC4]

    <add key="vs:EnableBrowserLink" value="false"/> 把这个加到 <appSettings /> ...

  8. GPS获取坐标 显示Google map偏差计算

    用手机获取GPS坐标 显示在手机地图偏差大约在100-200米左右,我把坐标放在 Maps.google.com 搜索坐标定位则相当精确. 可能是.....为了安全吧故意加的偏差 不过可以计算偏差使位 ...

  9. tools、site

    notepad editer fiddler 一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的"进出"Fiddler的数据 ...

  10. fragment--的生命周期

    官网帮助文档链接: http://developer.Android.com/guide/components/fragments.html 主要看两张图,和跑代码 1,Fragment的生命周: 2 ...