栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring源码IOC之无参实例化策略

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring源码IOC之无参实例化策略

无参实例化策略
        • 2.6 无参实例化策略
          • 2.6.1 getInstantiationStrategy 获取实例化策略
          • 2.6.2 实例化策略概览
          • 2.6.3 反射
          • 2.6.4 CGLIB

2.6 无参实例化策略

上文提到了IOC实例化bean的几种策略,接下来的小节,重点分析无参、有参两种实例化策略。因为无参策略较为简单,所以先分析该策略。

入口代码:

// 获取实例化策略,并实例化bean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
2.6.1 getInstantiationStrategy 获取实例化策略
private InstantiationStrategy instantiationStrategy;


public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
	this.instantiationStrategy = instantiationStrategy;
}


protected InstantiationStrategy getInstantiationStrategy() {
	return this.instantiationStrategy;
}

从代码中可以看到,IOC通过InstantiationStrategy接口来管理实例化策略,并且默认为CglibSubclassingInstantiationStrategy。但是IOC容器并没有显示的调用setInstantiationStrategy设置实例化策略,而是通过AbstractAutowireCapableBeanFactory的构造方法来创建实例化策略。

public AbstractAutowireCapableBeanFactory() {
	super();
	ignoreDependencyInterface(BeanNameAware.class);
	ignoreDependencyInterface(BeanFactoryAware.class);
	ignoreDependencyInterface(BeanClassLoaderAware.class);
	if (NativeDetector.inNativeImage()) {
		this.instantiationStrategy = new SimpleInstantiationStrategy();
	}
	else {
	   // 实例化 CglibSubclassingInstantiationStrategy
		this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
	}
}
2.6.2 实例化策略概览

上一步拿到实例化策略后,就可以实例化bean了。

@Override
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>) 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.
		// 存在方法注入,必须使用 CGLIB
		return instantiateWithMethodInjection(bd, beanName, owner);
	}
}

无方法注入,使用反射;否则,必须使用CGLIB

2.6.3 反射
  • 获取构造方法
    • constructorToUse = clazz.getDeclaredConstructor(); 通过Class类的getDeclaredConstructor()方法获取构造函数。因为这里是无参策略,所以无需传递任何参数。获取到构造方法后,再将其缓存到resolvedConstructorOrFactoryMethod中,方便下次使用。
  • 通过BeanUtils创建对象实例
    • 通过Constructor类的newInstance方法创建对象实例
2.6.4 CGLIB

若存在方法注入(replace-method、lookup-method)则必须使用CGLIB。

public Object instantiate(@Nullable Constructor ctor, 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() + 
		}
	}
	// SPR-10785: set callbacks directly on the instance instead of in the
	// enhanced class (via the Enhancer) in order to avoid memory leaks.
	// 为了避免内存泄漏,直接在实例上设置回调,而不是在增强类中(通过Enhancer)。
	Factory factory = (Factory) instance;
	factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
			new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
			new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
	return instance;
}

首先创建增强子类:

private Class createEnhancedSubclass(RootBeanDefinition beanDefinition) {
	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));
	}
	enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
	enhancer.setCallbackTypes(CALLBACK_TYPES);
	return enhancer.createClass();
}

Spring使用了Enhancer来创建增强子类,因为是动态字节码,所以我们需要将生成的增强文件保存到磁盘。在测试方法中添加:

// 替换成自己的路径
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/liyanchao/Downloads");

OK,接下来就可以看到生成的增强子类了,因为代码较多,只粘贴核心代码:

public class OriginalDog$$EnhancerBySpringCGLIB$$236d11d6 extends OriginalDog implements Factory {
    public final void sayHello() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_2;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_2;
        }
        if (var10000 != null) {
            // 拦截方法
            var10000.intercept(this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
        } else {
            super.sayHello();
        }
    }
}

有了增强子类后,接下来通过instance = BeanUtils.instantiateClass(subclass);创建对象实例,注意:这里创建的实例已经不是我们原始Bean的实例了,而是增强子类的实例。

当调用增强类中的方法时,会被intercept()方法拦截:

// replace_method
@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);
}
// lookup_method
@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())) {
		Object bean = (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
				this.owner.getBean(lo.getBeanName()));
		// Detect package-protected NullBean instance through equals(null) check
		return (bean.equals(null) ? null : bean);
	}
	else {
		// Find target bean matching the (potentially generic) method return type
		ResolvableType genericReturnType = ResolvableType.forMethodReturnType(method);
		return (argsToUse != null ? this.owner.getBeanProvider(genericReturnType).getObject(argsToUse) :
				this.owner.getBeanProvider(genericReturnType).getObject());
	}
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/298425.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号