一、Bean的实例化
- Spring中的获取的Bean,可能是原始对象,也可能是代理对象(JDK或CGLIB)
- 所以我们应该至少提供两种实例化的方式,直接new或者是CGLIB
二、策略模式
由于实例化的方式很多,我们这里使用策略模式,便于以后不断地扩展
先扩展一下BeanFactory接口,获取bean的时候,可以传入参数,这样就可以使用带参数的构造器
java
public interface BeanFactory {
Object getBean(String name);
Object getBean(String name, Object... args);
}
定义实例化策略接口
java
public interface InstantiationStrategy {
Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args);
}
改造doCreateBean方法,灵活切换对象实例化的方式
- 此处使用最简单的逻辑,直接根据传入的参数数量,匹配对应的构造器
java
/**
* 负责创建Bean
*
* @Author 孤风雪影
* @Email gitee.com/efairy520
* @Date 2025/1/1 1:01
* @Version 1.0
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
private final InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
/**
* 实现父类未实现的createBean方法
* @param beanName
* @param beanDefinition
* @return
*/
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) {
Object bean = doCreateBean(beanName, beanDefinition, args);
addSingleton(beanName, bean);
return bean;
}
protected Object doCreateBean(String beanName, BeanDefinition beanDefinition, Object[] args) {
Constructor constructorToUse = null;
Class<?> beanClass = beanDefinition.getBeanClass();
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
for (Constructor<?> ctor : declaredConstructors) {
//简易逻辑,只比较数量
if (null != args && ctor.getParameterTypes().length == args.length) {
constructorToUse = ctor;
break;
}
}
return instantiationStrategy.instantiate(beanDefinition, beanName, constructorToUse, args);
}
}
三、简单实例化策略
使用传入的构造器和传入的参数表,直接new对象
java
/**
* @Author 孤风雪影
* @Email gitee.com/efairy520
* @Date 2025/1/2 0:01
* @Version 1.0
*/
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) {
Class clazz = beanDefinition.getBeanClass();
try {
if (ctor != null) {
return clazz.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
} else {
return clazz.getDeclaredConstructor().newInstance();
}
} catch (Exception e) {
throw new RuntimeException("Failed to instantiate" + e);
}
}
}
四、CGLIB实例化策略
使用传入的构造器和传入的参数表,创建CGLIB代理对象
java
/**
* @Author 孤风雪影
* @Email gitee.com/efairy520
* @Date 2025/1/2 0:12
* @Version 1.0
*/
public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy{
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setCallback(new NoOp() {
@Override
public int hashCode() {
return super.hashCode();
}
});
if (null == ctor) return enhancer.create();
return enhancer.create(ctor.getParameterTypes(), args);
}
}
五、测试
给测试的Bean,新建空参构造器和有参构造器
java
package cn.shopifymall.springframework.test.bean;
/**
* @Author 孤风雪影
* @Email gitee.com/efairy520
* @Date 2025/2/6 23:15
* @Version 1.0
*/
public class UserService {
private String name;
public UserService() {
this.name = "undefined";
}
public UserService(String name) {
this.name = name;
}
public void queryUserInfo() {
System.out.println("查询用户信息:" + name);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("");
sb.append("").append(name);
return sb.toString();
}
}
测试代码
java
public class ApiTest {
@Test
public void test_BeanFactory(){
// 1.初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 注入bean
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
// 3.获取bean
UserService userService = (UserService) beanFactory.getBean("userService", "abc");
userService.queryUserInfo();
}
}
测试以下四种场景
- 简单策略空参
- 简单策略带参
- CGLIB策略空参
- CGLIB策略带参