spring 之 lookup-method & replace-method
初始化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的更多相关文章
- .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 ...
- 错误: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 ...
- Spring 通过工厂方法(Factory Method)来配置bean
Spring 通过工厂方法(Factory Method)来配置bean 在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. ...
- 『重构--改善既有代码的设计』读书笔记----Replace Method with Method Object
有时候,当你遇到一个大型函数,里面的临时变量和参数多的让你觉得根本无法进行Extract Method.重构中也大力的推荐短小函数的好处,它所带来的解释性,复用性让你收益无穷.但如果你遇到上种情况,你 ...
- 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 ...
- 重构 改善既有代码的设计 Replace Method with Method Object(以函数对象取代函数)
你有一个大型函数,其中对局部变量的使用使你无法采用Extract Method. 将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段.然后你可以在同一个对象中将这个大型函数分解为多个小型 ...
- 关于.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 ...
- 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类中的方法,又多此一举的单独整 ...
- Python OOP(2)-static method,class method and instance method
静态方法(Static Method): 一种简单函数,符合以下要求: 1.嵌套在类中. 2.没有self参数. 特点: 1.类调用.实例调用,静态方法都不会接受自动的self参数. 2.会记录所有实 ...
- 1.spring.net Look-up Method 查找方法的注入(方法是抽象的需要spring.net注入)
.为什么需要查找方法的注入 当Object依赖另一个生命周期不同的Object,尤其是当singleton依赖一个non-singleton时,常会遇到不少问题,Lookup Method Injec ...
随机推荐
- 未找到路径“/Agent/SissQrTemplate/AddN”的控制器或该控制器未实现 IController。
未找到路径“/Agent/SissQrTemplate/AddN”的控制器或该控制器未实现 IController. Controller 命名空间错误,应该是Areas.Agent.Controll ...
- html多个水平并列组件自适应等高的做法
做一个div盒子,设置over-flow:hidden,设置高度为auto.然后再盒子里排列若干inline-block,inline元素. 自适应的话常用做法是用line-height,font-s ...
- 纯css实现
实现此效果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!DOCTYPE html><html lang=& ...
- 【分布式session】Spring-session的使用
概述 Session用于保存用户信息,通常一个Session保存一个用户信息,在以Tomcat为Servlet Container的web应用中,用户信息都保存在HttpSession中: 当用户发起 ...
- Memcached在.NET应用程序中的使用
在应用程序运行的过程中总会有一些经常需要访问并且变化不频繁的数据,如果每次获取这些数据都需要从数据库或者外部文件系统中去读取,性能肯定会受 到影响,所以通常的做法就是将这部分数据缓存起来,只要数据没有 ...
- 无法启动程序,因为计算机中丢失mfc90ud.dll的解决方案
我的编程环境是vs2008-MFC,电脑系统是win7(64位) 解决方法:“工具”—>“选项”—>“项目和解决方案”—>“VC++目录”,在可执行文件栏中加上如下路径: $(Sys ...
- python输出缓冲区的问题
碰到的问题,一段代码,print在前,log的在后,查看日志中log的反而在前面.是python输出缓冲区的问题. python输出缓冲区要满 4k 才写入文件,除非禁用缓存或者强制输出或者程序结束. ...
- [UE4]函数和事件的区别
一.函数有返回值,事件无返回值 二.函数调用会等待函数执行结果,事件调用只是触发但不会等待. 三.函数执行在同一个线程,事件执行在不同线程. 四.函数可以用局部变量,事件没有局部变量. 五.因为函数执 ...
- CentOS安装Git,并上传、下载
转自:https://blog.csdn.net/u014066037/article/details/70224780 Git 一.安装Git $ yum install git 二. 生成SSH密 ...
- sas基础系列(3)-表格标颜色示例
以下代码可以直接在SAS执行查看效果 ods path reset;ods path show;ods html close;options nodate;ods pdf file="Pro ...