在看InstantiationStrategy之前我们先来简单的回顾下我们bean的实例化过程:
- 我们在AbstractAutowireCapableBeanFactory#doCreateBean(...)方法中完成了bean的创建过程,期间在该方法中有bean的初始化 属性的设置以及bean的实例化入口,其中在bean的实例化过程中是根据bean的类型进行判断,如果当前bean是单例,从factoryBeanInstanceCach中获取,反之通过#createBeanInstance(...)来创建.
- 如果是通过#createBeanInstance(...)方法进行bean实例的创建:
- 通过Supplier来判断,该Supplier不为null,则通过方法#obtainFromSupplier(...)进行bean的实例化操作.
- 如果factory不为null,则调用 #instantiateUsingFactoryMethod(...) 方法来实例化Bean.
- 如果都不是上面的两者,则调用默认的方法#instantiateBean(...)来完成bean的实例化操作.
不过上述是如何操作的过程,其最终都会经过InstantiationStrategy的instantiate(....)方法,接下来我们看一下该InstantiationStrategy接口:
InstantiationStrategy
public interface InstantiationStrategy {
/**
* 默认的构造方法
* @param bd
* @param beanName
* @param owner
* @return
* @throws BeansException
*/
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)throws BeansException;
/**
* 指定构造方法
* @param bd
* @param beanName
* @param owner
* @param ctor
* @param args
* @return
* @throws BeansException
*/
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Constructor<?> ctor, Object... args) throws BeansException;
/**
* 通过指定的工厂方法
* @param bd
* @param beanName
* @param owner
* @param factoryBean
* @param factoryMethod
* @param args
* @return
* @throws BeansException
*/
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, Method factoryMethod, Object... args)
throws BeansException;
可以看到的是InstantiationStrategy接口为Bean的初始化提供了三种策略化方法,根据bean的不同选择不同的策略模式进行实例化过程,我们分别来看:
1.默认的构造方法
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
//如果没有方法被覆盖,通过BeanUtils#instantiateClass来初始化(实质是利用反射来创建)
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
//加锁
synchronized (bd.constructorArgumentLock) {
//获取构造方法constructorToUse
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
//获取Bean的class的对象
final Class<?> clazz = bd.getBeanClass();
//如果clazz是接口类型的,直接抛BeanInstantiationException异常
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();
}
//将constructorToUse赋给resolvedConstructorOrFactoryMethod属性
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//通过BeanUtils直接使用构造器对象实例化Bean对象
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
//生成CGLIB创建的子类对象
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
在构造方法策略模式中,首先是判断是否有方法被覆盖,如果没有则直接通过反射的方式来创建,如果有的话则通过CGLIB来实例化对象.
2.指定的构造方法
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, 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;
});
}
//通过 BeanUtils直接使用构造器对象实例化Bean对象
return BeanUtils.instantiateClass(ctor, args);
}
else {
//2初始化CGLB对象
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
通过指定的构造方法我们可以发现跟默认的构造方法类似
3.工厂方法
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, 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中
currentlyInvokedFactoryMethod.set(factoryMethod);
//创建bean对象
Object result = factoryMethod.invoke(factoryBean, args);
//没创建成功,则创建一个nullBean来代替
if (result == null) {
result = new NullBean();
}
//创建成功的话,直接返回
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
//覆盖之前的方法
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
//后面都是些异常处理
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(factoryMethod,
"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(factoryMethod,
"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
}
catch (InvocationTargetException ex) {
String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
"declaring the factory method as static for independence from its containing instance. " + msg;
}
throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
}
}
工厂方法的处理更简单直接,不用考虑,直接利用反射的方式来初始化对象
CglibSubclassingInstantiationStrategy
关于CglibSubclassingInstantiationStrategy,该类继承于SimpleInstantiationStrategy与此同时该类也是spring默认的实例化bean的策略,也是CGLIB实例化bean的委托对象的实现类.
在我们的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);
}
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Constructor<?> ctor, Object... args) {
// Must generate CGLIB subclass...
//生成一个CGLB子类对象
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}
我们可以发现,显然子类CglibSubclassingInstantiationStrategy中对该方法进行了增强处理.其实例化bean的时候实际上是由CglibSubclassCreator来实现:
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
//创建一个cglb的代理类
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
//<2>如果当前构造器不存在,通过BeanUtils调用默认构造器来创建
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);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
//避免内存泄露,直接在bean实例上设置回调
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的增强子类,代码如下:
/**
* Create an enhanced subclass of the bean class for the provided bean
* definition, using CGLIB.
*/
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
//创建Enhancer对象
Enhancer enhancer = new Enhancer();
//设置当前bean的class类型
enhancer.setSuperclass(beanDefinition.getBeanClass());
//设置spring的命名策略
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();
}
在<2>处,如果ctor为null时,则通过BeanUtils#instantiateClass(subclass)来实例化bean,否则则根据构造函数类型获取具体的构造器,调用Constructor#newInstance(args) 方法来实例化.
MethodOverrideCallbackFilter
在我们的#createEnhancedSubclass(...)方法中的末尾,我们通过过滤,自定义逻辑来指定调用的callback下标,也就是以下代码:
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
我们发现在设置CallbackFilter属性时首先是创建一个MethodOverrideCallbackFilter对象,我们来看看它到底是什么?
- 原来发现MethodOverrideCallbackFilter继承于CglibIdentitySupport同时实现了CallbackFilter接口.
- 其次CallbackFilter是一个CGLIB 的一个回调过滤器接口.
- CglibIdentitySupport 则为 CGLIB 提供 #hashCode() 和 #equals(Object o) 方法,以确保 CGLIB 不会为每个 Bean 生成不同的类.
- MethodOverrideCallbackFilter 实现 CallbackFilter 的 #accept(Method method) 方法:
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());
}
在accept方法中,通过其methodOverride返回的值来判断,其中上述代码中的PASSTHROUGH 和 LOOKUP_OVERRIDE以及METHOD_REPLACER为Callback数组的下标,这里的数组为CALLBACK_TYPES数组,代码如下:
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
在上述的数组中我们看到定义了两个拦截器,接下来我们分别来看:
LookupOverrideMethodInterceptor
/**
* CGLIB MethodInterceptor to override methods, replacing them with an
* implementation that returns a bean looked up in the container.
*/
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.
//通过method来获取LookupOverride对象
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
//获取bean
if (StringUtils.hasText(lo.getBeanName())) {
//如果参数argsToUse不为null,通过name去获取
return (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
this.owner.getBean(lo.getBeanName()));
}
else {
//通过type去获取
return (argsToUse != null ? this.owner.getBean(method.getReturnType(), argsToUse) :
this.owner.getBean(method.getReturnType()));
}
}
}
ReplaceOverrideMethodInterceptor
/**
* CGLIB MethodInterceptor to override methods, replacing them with a call
* to a generic MethodReplacer.
*/
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 {
//通过method来获取ReplaceOverride对象
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对象
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
//进行替换操作
return mr.reimplement(obj, method, args);
}
}
到这里,关于初始化的策略模式知识我们讲到这里了...
网友评论