怀念过去,不满当下,迷惑未来,那么,努力吧!总得找个方式让自己转移一下注意力。
Spring版本
5.2.5.RELEASE
参考
《芋道源码》
源码解读
1 InstantiationStrategy
在《Spring源码解析(九)-创建bean实例》中,使用了instantiate
方法来执行Spring Bean实例化策略:
// 如果候选方法只有一个,并且没有要求参数,且有无参构造方法,那么,满足创建bean的要求,进行实例化
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.get(0);
// 如果唯一的候选方法参数个数为=0,满足mbd的无参构造方法
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
其中,instantiate
方法实现如下:
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction
可以看到通过getInstantiationStrategy()
方法调用了对应的实例化策略进行实例化,getInstantiationStrategy()
返回一个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, Object... args) throws BeansException;
// 工厂方法
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, Method factoryMethod, Object... args)
throws BeansException;
}
InstantiationStrategy
有俩个实现类:
SimpleInstantiationStrategy
CglibSubclassingInstantiationStrategy
2 SimpleInstantiationStrategy
该类实现了InstantiationStrategy
的三个方法
2.1 无参构造
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果没有replace-method、lookup-method,以及使用@Lookup注解,那么使用反射进行实例化
if (!bd.hasMethodOverrides()) {
Constructor> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 获取构造方法
constructorToUse = (Constructor>) bd.resolvedConstructorOrFactoryMethod;
// 未能获取到构造方法,尝试通过clazz获取
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);
}
}
首先判断是否存在replace-method
、lookup-method
,以及使用@Lookup
注解:
- 不存在,获取构造方法,之后通过构造方法进行实例化
- 存在,调用
instantiateWithMethodInjection
方法
查看instantiateWithMethodInjection
方法,可以看到在SimpleInstantiationStrategy
中是默认不实现的:
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
}
交由CglibSubclassingInstantiationStrategy
进行实现
2.2 有参构造
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor> ctor, Object... args) {
// 如果没有replace-method、lookup-method,以及使用@Lookup注解,那么使用反射进行实例化
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction
同样,判断是否存在replace-method
、lookup-method
,以及使用@Lookup
注解:
- 不存在,通过传入的构造方法进行实例化
- 存在,调用
instantiateWithMethodInjection
方法
2.3 工厂方法
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
// 设置method方法可访问
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
先通过ReflectionUtils.makeAccessible(factoryMethod)
设置工厂方法可以访问,之后通过Object result = factoryMethod.invoke(factoryBean, args)
反射调用工厂方法获取实例
3 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...
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}
在第二个重载方法中,可以看到构造了一个CglibSubclassCreator
对象,之后通过instantiate
进行了实例化:
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() + "]", ex);
}
}
// 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;
}
3.1 createEnhancedSubclass
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();
}
MethodOverrideCallbackFilter
是用来定义 CGLIB 回调过滤方法的拦截器行为,它继承 CglibIdentitySupport
实现CallbackFilter
接口:
private static class MethodOverrideCallbackFilter extends CglibIdentitySupport implements CallbackFilter {
private static final Log logger = LogFactory.getLog(MethodOverrideCallbackFilter.class);
public MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) {
super(beanDefinition);
}
@Override
public int accept(Method method) {
MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
if (logger.isTraceEnabled()) {
logger.trace("MethodOverride for " + method + ": " + 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
方法,返回的PASSTHROUGH
、LOOKUP_OVERRIDE
和METHOD_REPLACER
对应的是CALLBACK_TYPES
数组的元素下标:
private static final Class>[] CALLBACK_TYPES = new Class>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
可以看到这里定义了LookupOverrideMethodInterceptor
和ReplaceOverrideMethodInterceptor
,通过这俩个拦截器对lookup-method
和replace-method
进行了处理。
3.2 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
// 通过getBean获取实例,然后返回该实例,以起到替换作用
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()));
}
}
}
3.3 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实例化bean对几种策略,及其对lookup-method
、replace-method
的代理处理,不过平时对于lookup-method
、replace-method
的使用较少,个人认为稍微理解一下就行,不必过于纠结细节,否则,学习起来进度应该相当缓慢,进而影响坚持下去的动力。