开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情
基于策略模式实现两种用于实例化对象的方法,如 JDK、Cglib,并基于此方法实现含邮带入参信息的构造函数的类实例化策略
如果之前的代码实例化有入餐信息的构造函数的类,就会报错。原因是:beanDefinition.getBeanClass().newInstance() 的实例化方法并没有考虑类中含有带入参信息的构造函数,所以会报异常。
实例化策略设计
1.如何将构造函数的入参信息合理地传递到实例化中
2.如何将入参信息的构造函数的类实例化
使用什么方式可以创建包含构造函数的Bean 对象?
1.基于Java 本身自带的方法 DeclaredConstructor
2.使用 Cglib 动态创建 Bean 对象
ps:Cglib 是基于 ASM 字节码框架实现。
核心
在上一节的基础上 添加 InstantiationStrategy 实例化策略接口、开发 JDK 和 Cglib 实例化方法,以此来实现带入参信息的构造函数的实例化
代码实现
pom - cglib 实例化添加代码
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
BeanFactory - 重写 带参数的 getBean 方法
public interface BeanFactory {
/**
* @Author: Take-off
* @Description: //TODO 返回Bean 的实例对象
* @Date: 10:01 AM 2022/12/12
* @Param: [name]
* @return: java.lang.Object
**/
Object getBean(String name) throws BeansException;
Object getBean(String name,Object... args) throws BeansException;
}
InstantiationStrategy - 实例化策略 接口
public interface InstantiationStrategy {
/**
* @Author: Take-off
* @Description: //TODO
* @Date: 8:57 PM 2022/12/13
* @Param: [beanDefinition, beanName, ctor, args] :ctor - 获取与入参信息相对应的构造函数
* @return: java.lang.Object
**/
Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException;
}
Constructor - 获取与入参信息相对应的构造函数
SimpleInstantiationStrategy - JDK实例化实现
public class SimpleInstantiationStrategy implements InstantiationStrategy{
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
Class beanClass = beanDefinition.getBeanClass();
try {
if (Optional.ofNullable(ctor).isPresent()){
//传递构造函数的入参、信息进行实例化
//将入参信息传递给 newInstance 进行实例化
return beanClass.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
}else {
//无构造函数
return beanClass.getDeclaredConstructor().newInstance();
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new BeansException("Failed to instantiate [" + beanClass.getName() + "]", e);
}
}
}
CglibSubclassingInstantiationStrategy - Cglib 实例化
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();
}
return enhancer.create(ctor.getParameterTypes(), args);
}
}
测试类
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","居头小刘");
userService.queryUserInfo();
}
}
public class UserService {
private String name;
public UserService(String name) {
this.name = name;
}
public void queryUserInfo(){
System.out.println("查询用户信息" + name);
}
}
总结
完善了实例化策略,增加了 InstantiationStrategy 实例化策略。