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();
	}
}
相关推荐
武子康26 分钟前
Java-72 深入浅出 RPC Dubbo 上手 生产者模块详解
java·spring boot·分布式·后端·rpc·dubbo·nio
_殊途1 小时前
《Java HashMap底层原理全解析(源码+性能+面试)》
java·数据结构·算法
椰椰椰耶2 小时前
【Spring】拦截器详解
java·后端·spring
没有bug.的程序员3 小时前
JAVA面试宝典 - 《MyBatis 进阶:插件开发与二级缓存》
java·面试·mybatis
没有羊的王K4 小时前
SSM框架学习——day1
java·学习
又菜又爱coding4 小时前
安装Keycloak并启动服务(macOS)
java·keycloak
不知道叫什么呀5 小时前
【C】vector和array的区别
java·c语言·开发语言·aigc
wan_da_ren5 小时前
JVM监控及诊断工具-GUI篇
java·开发语言·jvm·后端
cui_hao_nan6 小时前
JAVA并发——什么是Java的原子性、可见性和有序性
java·开发语言
best_virtuoso6 小时前
JAVA JVM垃圾收集
java·开发语言·jvm