JDK和Cglib动态代理实例化策略

日志

在上一节中,出现了一个小问题:没法实例化有参构造对象

本章节有以下变动:

  • 使用Cglib字节码方式、JDK内部方式进行有参对象的实例化
  • 后续章节可采用策略模式优化策略的选择

手写Spring-属性注入

这里不小心把下一节的 UML 画了。。。

因为比较简单,就只展示 Cglib 字节码和 JDK 两种实例化对象的代码了

Cglib方式:

@SuppressWarnings({"rawtypes"})
public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy {

@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
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();
}
assert ctor != null;
return enhancer.create(ctor.getParameterTypes(), args);
}

}
  • 核心方法为 Enhancer.create

JDK方式:

@SuppressWarnings({"rawtypes"})
public class SimpleInstantiationStrategy implements InstantiationStrategy {

@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
Class clazz = beanDefinition.getBeanClass();

try {
if (args != null) {
// 有参构造
return clazz.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
} else {
// 无参构造
return clazz.getDeclaredConstructor().newInstance();
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new BeansException("Failed to instantiate [" + clazz.getName() + "]"
+ " -- [" + clazz.getName() + "] 实例化失败", e);
}
}

}
  • 核心方法:getDeclaredConstructor(…)

具体的调用在 AbstractAutowrieCapableBeanFactory

测试

@Test
public void test_BeanFactory() {
// 1. 初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanF
actory();

// 2. 注册 Bean
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);

// 3. 无参 Bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();

// 4. 有参 Bean 有 bug, bean 没法区分有参无参
UserService userService_args = (UserService) beanFactory.getBean("userService", "半糖");
userService_args.queryUserInfo();
}

_dnsauth

202405010000001c5kq42954wu3x1udfifby92t5uw4pfdnl57d3lkwi0zz6p5ur