简介
SimpleInstantiationStrategy 是 Spring 框架中的一个类,它属于 Spring Bean 的实例化策略。在 Spring 中,Bean 的实例化过程可以通过不同的策略来控制,这些策略通常实现了 InstantiationStrategy 接口。SimpleInstantiationStrategy 是这个接口的一个简单实现,也是 Spring 默认使用的实例化策略。
InstantiationStrategy 接口的主要目的是控制 Spring 容器中 Bean 的实例化过程。它提供了一个 instantiate() 方法,该方法用于创建 Bean 的实例。
SimpleInstantiationStrategy 类的 instantiate() 方法的行为相对简单。它直接调用 Class 的 newInstance() 方法来创建 Bean 的实例。这种方法要求 Bean 的类有一个无参数的构造器。
源码
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@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<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//通过无参构造方法实例化bean
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
}
BeanUtils.instantiateClass()方法
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
return KotlinDelegate.instantiateClass(ctor, args);
}
else {
Class<?>[] parameterTypes = ctor.getParameterTypes();
Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
Object[] argsWithDefaultValues = new Object[args.length];
for (int i = 0 ; i < args.length; i++) {
if (args[i] == null) {
Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
else {
argsWithDefaultValues[i] = args[i];
}
}
return ctor.newInstance(argsWithDefaultValues);
}
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}
尽管 SimpleInstantiationStrategy 是默认的实例化策略,但 Spring 也提供了其他的策略,如 CglibSubclassingInstantiationStrategy,它使用 CGLIB 库来创建 Bean 的子类实例,这样可以支持有构造器参数的情况。
你可以通过配置来更改 Spring 使用的实例化策略。例如,在 XML 配置中,你可以通过 元素的 init-method 和 destroy-method 属性来指定初始化和销毁方法,这实际上也是影响 Bean 的实例化过程。在 Java 配置或注解配置中,你可以通过编程方式来更改实例化策略。
注意:直接操作或更改实例化策略通常只在高级用途或特殊情况下需要。在大多数情况下,使用默认的 SimpleInstantiationStrategy 就足够了。