1、创建你的pojo对象
package cn.pojo;
/**
* @author zhr_java@163.com
* @date 2022/4/17 22:03
*/
public class UserDao {
public void queryUserInfo(){
System.out.println("hello world!!!");
}
}
2、创建resources文件夹并创建beans.properties文件
注意:cn.pojo.UserDao要对应填写你自己创建的
userDao:cn.pojo.UserDao
3、定义Bean
package cn.bean;
/**
* bean定义类,配置文件中bean定义对应的实体
*
* @author zhr_java@163.com
* @date 2022/4/17 21:56
*/
public class BeanDefinition {
private String beanName;
private Class beanClass;
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
}
4、资源加载
package cn.utils;
import cn.bean.BeanDefinition;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
/**
* @author zhr_java@163.com
* @date 2022/4/17 22:12
*/
public class ResourceLoader {
public static Map<String, BeanDefinition> getResource() {
Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(16);
Properties properties = new Properties();
try {
InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");
properties.load(inputStream);
Iterator<String> it = properties.stringPropertyNames().iterator();
while (it.hasNext()) {
String key = it.next();
String className = properties.getProperty(key);
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanName(key);
Class clazz = Class.forName(className);
beanDefinition.setBeanClass(clazz);
beanDefinitionMap.put(key, beanDefinition);
}
inputStream.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return beanDefinitionMap;
}
}
5、Bean注册
package cn.bean;
import java.util.HashMap;
import java.util.Map;
/**
* 对象注册器,这里用于单例bean的缓存,我们大幅简化,默认所有bean都是单例的。可以看到所谓单例注册,也很简单,不过是往HashMap里存对象。
*
* @author zhr_java@163.com
* @date 2022/4/17 21:59
*/
public class BeanRegister {
/** 单例Bean缓存 */
private Map<String, Object> singletonMap = new HashMap(32);
/**
* 获取单例Bean
*
* @param beanName bean名称
* @return
*/
public Object getSingletonBean(String beanName) {
return singletonMap.get(beanName);
}
/**
* 注册单例bean
*
* @param beanName
* @param bean
*/
public void registerSingletonBean(String beanName, Object bean) {
if (singletonMap.containsKey(beanName)) {
return;
}
singletonMap.put(beanName, bean);
}
}
6、对象工厂
package cn.factory;
import cn.bean.BeanDefinition;
import cn.bean.BeanRegister;
import cn.utils.ResourceLoader;
import java.util.HashMap;
import java.util.Map;
/**
* 获取bean的时候,先从单例缓存中取,如果没有取到,就创建并注册一个bean
*
* @author zhr_java@163.com
* @date 2022/4/17 22:00
*/
public class BeanFactory {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap();
private BeanRegister beanRegister;
public BeanFactory() {
// 创建bean注册器
beanRegister = new BeanRegister();
// 加载资源
this.beanDefinitionMap = ResourceLoader.getResource();
}
/**
* 获取bean
*
* @param beanName bean名称
* @return
*/
public Object getBean(String beanName) {
// 从bean缓存中取
Object bean = beanRegister.getSingletonBean(beanName);
if (bean != null) {
return bean;
}
// 根据bean定义,创建bean
return createBean(beanDefinitionMap.get(beanName));
}
/**
* 创建Bean
*
* @param beanDefinition bean定义
* @return
*/
private Object createBean(BeanDefinition beanDefinition) {
try {
Object bean = beanDefinition.getBeanClass().newInstance();
// 缓存bean
beanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);
return bean;
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
7、测试
package cn;
import cn.factory.BeanFactory;
import cn.pojo.UserDao;
/**
* @author zhr_java@163.com
* @date 2022/4/17 22:03
*/
public class ApiTest {
public static void main(String[] args) {
//1.创建bean工厂(同时完成了加载资源、创建注册单例bean注册器的操作)
BeanFactory beanFactory = new BeanFactory();
//2.第一次获取bean(通过反射创建bean,缓存bean)
UserDao userDao1 = (UserDao) beanFactory.getBean("userDao");
userDao1.queryUserInfo();
//3.第二次获取bean(从缓存中获取bean)
UserDao userDao2 = (UserDao) beanFactory.getBean("userDao");
userDao2.queryUserInfo();
}
}
效果图:
总结:实际上先通过spi的方式把编译前的bean资源加载,在工厂方法中初始化,在调用bean的时候通过单例的方式获取,如果是第一次获取就通过加载过的资源实例化bean,如果不是就根据bean名称返回bean