mini-spring-Bean含参实例化(三)

上一节,bean是在AbstractAutowireCapableBeanFactory.doCreateBean方法中用beanClass.newInstance()来实例化,仅适用于bean有无参构造函数的情况。

本节考虑含参的bean的实例化

考虑两个问题

一、串流程从哪合理的把构造函数的入参信息传递到实例化操作里

BeanFactory 中添加 Object getBean(String name, Object... args) 接口,AbstractBeanFactory中使用doGetBean实现接口

二、怎么去实例化含有构造函数的对象。,

使用动态代理的方式实例化bean对象

新增 getBean 接口

java 复制代码
public interface BeanFactory {

    Object getBean(String name) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

}

定义实例化策略接口

java 复制代码
public interface InstantiationStrategy {
	/**
	 *
	 * @param beanDefinition bean定义信息
	 * @param beanName bean名称
	 * @param ctor 含了一些必要的类信息,有这个参数的目的就是为了拿到符合入参信息相对应的构造函数
	 * @param args 具体的含参信息
	 * @return
	 * @throws BeansException
	 */
//	Object instantiate(BeanDefinition beanDefinition) throws BeansException;
Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException;
}

JDK 实例化

首先通过 beanDefinition 获取 Class 信息,这个 Class 信息是在 Bean 定义的时候传递进去的。

接下来判断 ctor 是否为空(判断有没有参数信息),如果为空则是无构造函数实例化,否则就是需要有构造函数的实例化。

java 复制代码
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 (null != ctor) {
				//clazz.getDeclaredConstructor返回指定参数的构造器 通过类对象访问
				return clazz.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
			} else {
				return clazz.getDeclaredConstructor().newInstance();
			}
		} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
			throw new BeansException("Failed to instantiate [" + clazz.getName() + "]", e);
		}
	}
}

Cglib 实例化

java 复制代码
public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy {

	/**
	 * 使用CGLIB动态生成子类
	 *
	 * @param beanDefinition
	 * @return
	 * @throws BeansException
	 */

	@Override
	public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
		//cglib工具类
		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 复制代码
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {

	private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
	//实现创建bean
	@Override
	protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
		Object bean = null;
		try {
			bean = createBeanInstance(beanDefinition, beanName, args);
		} catch (Exception e) {
			throw new BeansException("Instantiation of bean failed", e);
		}

		addSingleton(beanName, bean);
		return bean;
	}

	protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, 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 getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
	}

	/**
	 * 属性的get set方法
	 * @return
	 */
	public InstantiationStrategy getInstantiationStrategy() {
		return instantiationStrategy;
	}
	public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
		this.instantiationStrategy = instantiationStrategy;
	}
}

测试

定义一个类'

java 复制代码
public class HelloService {


		private String name;

		public HelloService(String name) {
			this.name = name;
		}

		public void queryUserInfo() {
			System.out.println("查询hello信息:" + name);
		}

		@Override
		public String toString() {
			final StringBuilder sb = new StringBuilder("");
			sb.append("").append(name);
			return sb.toString();
		}
}
java 复制代码
public class BeanDefinitionAndBeanDefinitionRegistryTest {

	@Test
	public void testBeanFactory() throws Exception {
		// 1.初始化 BeanFactory
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		// 3. 注入bean
		BeanDefinition beanDefinition = new BeanDefinition(HelloService.class);
		beanFactory.registerBeanDefinition("helloService", beanDefinition);
		// 4.获取bean
		HelloService helloService = (HelloService) beanFactory.getBean("helloService", "我的参数");
		helloService.queryUserInfo();
	}
}
相关推荐
用户61204149221319 分钟前
使用JSP+Servlet+JavaBean做的课程后台管理系统
java·javascript·mysql
乌暮26 分钟前
数据库--JDBC编程
java·数据库·学习
小白黑科技测评41 分钟前
2025 年视频去水印工具实测:擦擦视频双版本解析一键去字幕与多格式兼容能力
java·人工智能·音视频·智能电视·1024程序员节
华仔啊1 小时前
Go 语言未来会取代 Java 吗?别争了,先看完这篇再说
java·后端·go
多多*1 小时前
Spring Bean的生命周期 第二次思考
java·开发语言·rpc
小丁努力不焦虑1 小时前
c++基本语法
java·c++·算法
Olrookie1 小时前
Maven快速上手笔记
java·笔记·maven
喵手2 小时前
调试技巧:从 IDE 调试到生产环境定位问题,提升调试效率的全方位指南
java·ide·调试
摇滚侠2 小时前
Spring Boot3零基础教程,定制 Health 健康端点,笔记83
spring boot·笔记·spring
芙蓉王真的好12 小时前
优化 Jenkins 构建脚本:避免 pnpm lockfile 相关报错的关键配置
spring·servlet·jenkins