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();
	}
}
相关推荐
煸橙干儿~~2 分钟前
分析JS Crash(进程崩溃)
java·前端·javascript
2401_854391083 分钟前
Spring Boot大学生就业招聘系统的开发与部署
java·spring boot·后端
Amor风信子4 分钟前
华为OD机试真题---跳房子II
java·数据结构·算法
杨荧30 分钟前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源
陈逸轩*^_^*1 小时前
Java 网络编程基础
java·网络·计算机网络
这孩子叫逆1 小时前
Spring Boot项目的创建与使用
java·spring boot·后端
星星法术嗲人1 小时前
【Java】—— 集合框架:Collections工具类的使用
java·开发语言
一丝晨光1 小时前
C++、Ruby和JavaScript
java·开发语言·javascript·c++·python·c·ruby
天上掉下来个程小白1 小时前
Stream流的中间方法
java·开发语言·windows
xujinwei_gingko2 小时前
JAVA基础面试题汇总(持续更新)
java·开发语言