在开始分析 InstantiationStrategy 之前,我们先来简单回顾下 bean 的实例化过程:
- bean 的创建,主要是
AbstractAutowireCapableBeanFactory.doCreateBean()
,在这个方法中有 bean 的实例化、属性注入和初始化过程,对于 bean 的实例化过程这是根据 bean 的类型来判断的,如果是单例模式,则直接从 factoryBeanInstanceCache 缓存中获取,否则调用createBeanInstance()
创建。 - 在
createBeanInstance()
中,如果 Supplier 不为空,则调用obtainFromSupplier()
实例化 bean。如果 factory 不为空,则调用instantiateUsingFactoryMethod()
实例化 bean ,如果都不是则调用instantiateBean()
实例化bean 。但是无论是instantiateUsingFactoryMethod()
还是instantiateBean()
最后都一定会调用到 InstantiationStrategy 接口的instantiate()
。
InstantiationStrategy
InstantiationStrategy 接口定义了 Spring Bean 实例化的策略,根据创建对象情况的不同,提供了三种策略:无参构造方法、有参构造方法、工厂方法。如下:
public interface InstantiationStrategy {
/**
* 默认构造方法
*/
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
throws BeansException;
/**
* 指定构造方法
*/
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Constructor<?> ctor, @Nullable Object... args) throws BeansException;
/**
* 工厂方法
*/
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, Method factoryMethod, @Nullable Object... args)
throws BeansException;
}
SimpleInstantiationStrategy
InstantiationStrategy 接口有两个实现类:SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy。SimpleInstantiationStrategy 对以上三个方法都做了简单的实现。
如果是工厂方法实例化,则直接使用反射创建对象,如下:
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, @Nullable Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
});
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
// 省略 catch
}
如果是构造方法实例化,则是先判断是否有 MethodOverrides,如果没有则是直接使用反射,如果有则就需要 CGLIB 实例化对象。如下:
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
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 = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, @Nullable Object... args) {
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
return (args != null ? BeanUtils.instantiateClass(ctor, args) : BeanUtils.instantiateClass(ctor));
}
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
SimpleInstantiationStrategy 对 instantiateWithMethodInjection()
的实现任务交给了子类 CglibSubclassingInstantiationStrategy。
MethodOverrides
对于 MethodOverrides,如果读者是跟着小编文章一路跟过来的话一定不会陌生,在 BeanDefinitionParserDelegate 类解析 <bean/>
的时候是否还记得这两个方法:parseLookupOverrideSubElements()
和 parseReplacedMethodSubElements()
这两个方法分别用于解析 lookup-method 和 replaced-method。parseLookupOverrideSubElements()
源码如下:
更多关于 lookup-method 和 replaced-method 请看:【死磕 Spring】----- IOC 之解析 bean 标签:meta、lookup-method、replace-method
CGLIB 实例化策略
类 CglibSubclassingInstantiationStrategy 为 Spring 实例化 bean 的默认实例化策略,其主要功能还是对父类功能进行补充:其父类将 CGLIB 的实例化策略委托其实现。
--- SimpleInstantiationStrategy
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
}
--- CglibSubclassingInstantiationStrategy
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
return instantiateWithMethodInjection(bd, beanName, owner, null);
}
CglibSubclassingInstantiationStrategy 实例化 bean 策略是通过其内部类 CglibSubclassCreator 来实现的。
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Constructor<?> ctor, @Nullable Object... args) {
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}
创建 CglibSubclassCreator 实例然后调用其 instantiate()
,该方法用于动态创建子类实例,同时实现所需要的 lookups(lookup-method、replace-method)。
public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass);
}
else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
//这个地方解决一个bug,bug提交报告https://jira.spring.io/browse/SPR-10785
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
调用 createEnhancedSubclass()
为提供的 BeanDefinition 创建 bean 类的增强子类。
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
// cglib里面的用法,对原始class进行增强,并设置callback
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
if (this.owner instanceof ConfigurableBeanFactory) {
ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
}
// 过滤,自定义逻辑来指定调用的callback下标
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
获取子类增强 class 后,如果 Constructor 实例 ctr 为空,则调用默认构造函数(BeanUtils.instantiateClass()
)来实例化类,否则则根据构造函数类型获取具体的构造器,调用 newInstance()
实例化类。在 createEnhancedSubclass()
我们注意两行代码:
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
通过 MethodOverrideCallbackFilter 来定义调用 callback 类型,MethodOverrideCallbackFilter 是用来定义 CGLIB 回调过滤方法的拦截器行为,它继承 CglibIdentitySupport 实现 CallbackFilter 接口, CallbackFilter 是 CGLIB 的一个回调过滤器,CglibIdentitySupport 则为 CGLIB 提供 hashCode()
和 equals()
方法,以确保 CGLIB 不会为每个 bean 生成不同的类。MethodOverrideCallbackFilter 实现 CallbackFilter accept()
:
public int accept(Method method) {
MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
if (logger.isTraceEnabled()) {
logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
}
if (methodOverride == null) {
return PASSTHROUGH;
}
else if (methodOverride instanceof LookupOverride) {
return LOOKUP_OVERRIDE;
}
else if (methodOverride instanceof ReplaceOverride) {
return METHOD_REPLACER;
}
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
methodOverride.getClass().getName());
}
根据 BeanDefinition 中定义的 MethodOverride 不同,返回不同的值, 这里返回的 PASSTHROUGH 、LOOKUP_OVERRIDE、METHOD_REPLACER 都是 Callbak 数组的下标,这里对应的数组为 CALLBACK_TYPES 数组,如下:
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
这里又定义了两个熟悉的拦截器 :LookupOverrideMethodInterceptor 和 ReplaceOverrideMethodInterceptor,两个拦截器分别对应两个不同的 callback 业务:
LookupOverrideMethodInterceptor
private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
private final BeanFactory owner;
public LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
// Cast is safe, as CallbackFilter filters are used selectively.
LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
Assert.state(lo != null, "LookupOverride not found");
Object[] argsToUse = (args.length > 0 ? args : null); // if no-arg, don't insist on args at all
if (StringUtils.hasText(lo.getBeanName())) {
return (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
this.owner.getBean(lo.getBeanName()));
}
else {
return (argsToUse != null ? this.owner.getBean(method.getReturnType(), argsToUse) :
this.owner.getBean(method.getReturnType()));
}
}
}
ReplaceOverrideMethodInterceptor
private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
private final BeanFactory owner;
public ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
Assert.state(ro != null, "ReplaceOverride not found");
// TODO could cache if a singleton for minor performance optimization
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
return mr.reimplement(obj, method, args);
}
}
通过这两个拦截器,再加上这篇博客:【死磕 Spring】----- IOC 之解析 bean 标签:meta、lookup-method、replace-method,是不是一道绝佳的美食。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。