Spring(3)手写Spring ioc模块(第三版)

整体思路

1、读取bean.xml文件
2、解析bean文件,将bean信息封装到BeanDefinition对象中

  • 加载并注册BeanDefinition流程
    XmlBeanDefinitionReader:整体就是负责读取Document对象
    XmlBeanDefinitionDocumentReader:整体就是负责BeanDefinition的注册工作

    • 解析bean标签以及自定义标签
    • 递归调用解析bean标签中子标签
    • 将解析出来的bean标签信息封装到BeanDefinition对象
  • 将BeanDefinition对象存放到BeanDefinitionRegistry 集合中

3、获取Bean实例
BeanFactory(工厂模式、接口隔离原理、抽象模板方法模式)

  • 查看SingletonBeanRegistry集合中是否存在该bean实例
    • 有则直接返回
    • 没有则需要查询BeanDefinition集合中是否存在该BeanDefinition
      • 没有返回null
      • 有则根据BeanDefinition属性创建(利用反射)不同属性的bean实例
        将单例bean存入bean集合,多例bean直接返回
  • 创建bean实例
    • 实例化 new
    • 属性填充 set
    • 初始化 init

4、通过Bean实例查询数据库

  • 获取statement
  • (利用反射)设置参数
  • 链接数据库,查询
  • (利用反射)处理结果集

处理流程图Spring(3)手写Spring ioc模块(第三版)_第1张图片
BeanFactory继承体系
Spring(3)手写Spring ioc模块(第三版)_第2张图片

测试类代码

public class TestSpringV3 {

	@Test
	public void test() throws Exception {
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

		XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		Resource resource = new ClasspathResource("beans.xml");

		InputStream inputStream = resource.getResource();

		xmlBeanDefinitionReader.loadBeanDefinitions(inputStream);

		UserService userService = (UserService) beanFactory. getBean("userService");

		User user = new User();
		user.setUsername("王五");
		List<User> users = userService.queryUsers(user);
		System.out.println(users);
	}
}

resource 包

Resource 接口

public interface Resource {

	InputStream getResource();
}

ClasspathResource 类 实现Resource 接口

  • 读取bean.xml 流文件
public class ClasspathResource implements Resource {

	private String location;

	public ClasspathResource(String location) {
		this.location = location;
	}

	@Override
	public InputStream getResource() {
		return this.getClass().getClassLoader().getResourceAsStream(location);
	}
}

utils 工具包

DocumentReader类

  • 创建Document对象
public class DocumentReader {

	/**
	 * 创建Document对象
	 * 
	 * @param inputStream
	 * @return
	 */
	public static Document createDocument(InputStream inputStream) {
		Document document = null;
		try {
			SAXReader reader = new SAXReader();
			document = reader.read(inputStream);
			return document;
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return null;
	}
}

ReflectUtils

  • 反射工具类
public class ReflectUtils {

	/**
	 * 使用构造器创建bean的实例
	 * 
	 * @param beanClassName
	 * @param args
	 * @return
	 */
	public static Object createObject(Class<?> clazz, Object... args) {
		try {
			// TODO 可以根据输入参数获取指定构造参数的构造方法
			Constructor<?> constructor = clazz.getConstructor();
			// 默认调用无参构造进行对象的创建
			return constructor.newInstance(args);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void setProperty(Object beanInstance, String name, Object valueToUse) {
		try {
			Class<?> clazz = beanInstance.getClass();
			Field field = clazz.getDeclaredField(name);
			field.setAccessible(true);
			field.set(beanInstance, valueToUse);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static Class<?> getTypeByFieldName(String beanClassName, String name) {
		try {
			Class<?> clazz = Class.forName(beanClassName);
			Field field = clazz.getDeclaredField(name);
			return field.getType();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void invokeMethod(Object beanInstance, String initMethod) {
		try {
			if (initMethod == null || "".equals(initMethod)) {
				return;
			}
			Class<?> clazz = beanInstance.getClass();
			Method method = clazz.getDeclaredMethod(initMethod);
			// 设置允许访问私有方法和变量,此处也称之为暴力破解
			method.setAccessible(true);
			method.invoke(beanInstance);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

springframework.reader 包

XmlBeanDefinitionReader 类

  • 整体就是负责读取Document对象
public class XmlBeanDefinitionReader {

	private BeanDefinitionRegistry beanDefinitionRegistry;

	public XmlBeanDefinitionReader(BeanDefinitionRegistry beanDefinitionRegistry) {
		this.beanDefinitionRegistry = beanDefinitionRegistry;
	}

	public void loadBeanDefinitions(InputStream inputStream) {
		Document document = DocumentReader.createDocument(inputStream);
		XmlBeanDefinitionDocumentReader documentReader = new XmlBeanDefinitionDocumentReader(beanDefinitionRegistry);
		documentReader.registerBeanDefinitions(document.getRootElement());
	}
}

XmlBeanDefinitionDocumentReader 类

  • 整体就是负责BeanDefinition的注册工作
public class XmlBeanDefinitionDocumentReader {

	private BeanDefinitionRegistry beanDefinitionRegistry;

	public XmlBeanDefinitionDocumentReader(BeanDefinitionRegistry beanDefinitionRegistry) {
		this.beanDefinitionRegistry = beanDefinitionRegistry;
	}

	@SuppressWarnings("unchecked")
	public void registerBeanDefinitions(Element rootElement) {
		// 获取和自定义标签(比如mvc:interceptors)
		List<Element> elements = rootElement.elements();
		for (Element element : elements) {
			// 获取标签名称
			String name = element.getName();
			if (name.equals("bean")) {
				// 解析默认标签,其实也就是bean标签
				parseDefaultElement(element);
			} else {
				// 解析自定义标签,比如mvc:interceptors标签回去
				parseCustomElement(element);
			}
		}

	}

	@SuppressWarnings("unchecked")
	private void parseDefaultElement(Element beanElement) {
		try {
			if (beanElement == null)
				return;
			// 获取id属性
			String id = beanElement.attributeValue("id");

			// 获取name属性
			String name = beanElement.attributeValue("name");
			// 获取class属性
			String clazzName = beanElement.attributeValue("class");
			if (clazzName == null || "".equals(clazzName)) {
				return;
			}
			Class<?> clazzType = Class.forName(clazzName);

			// 获取init-method属性
			String initMethod = beanElement.attributeValue("init-method");
			// 获取scope属性
			String scope = beanElement.attributeValue("scope");
			scope = scope != null && !scope.equals("") ? scope : "singleton";

			String beanName = id == null ? name : id;
			beanName = beanName == null ? clazzType.getSimpleName() : beanName;
			// 创建BeanDefinition对象
			// 此次可以使用构建者模式进行优化
			BeanDefinition beanDefinition = new BeanDefinition(clazzName, beanName);
			beanDefinition.setInitMethod(initMethod);
			beanDefinition.setScope(scope);
			// 获取property子标签集合
			List<Element> propertyElements = beanElement.elements();
			for (Element propertyElement : propertyElements) {
				parsePropertyElement(beanDefinition, propertyElement);
			}

			// 注册BeanDefinition信息
			beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	private void parsePropertyElement(BeanDefinition beanDefination, Element propertyElement) {
		if (propertyElement == null)
			return;

		// 获取name属性
		String name = propertyElement.attributeValue("name");
		// 获取value属性
		String value = propertyElement.attributeValue("value");
		// 获取ref属性
		String ref = propertyElement.attributeValue("ref");

		// 如果value和ref都有值,则返回
		if (value != null && !value.equals("") && ref != null && !ref.equals("")) {
			return;
		}

		/**
		 * PropertyValue就封装着一个property标签的信息
		 */
		PropertyValue pv = null;

		if (value != null && !value.equals("")) {
			// 因为spring配置文件中的value是String类型,而对象中的属性值是各种各样的,所以需要存储类型
			TypedStringValue typeStringValue = new TypedStringValue(value);

			Class<?> targetType = ReflectUtils.getTypeByFieldName(beanDefination.getClazzName(), name);
			typeStringValue.setTargetType(targetType);

			pv = new PropertyValue(name, typeStringValue);
			beanDefination.addPropertyValue(pv);
		} else if (ref != null && !ref.equals("")) {

			RuntimeBeanReference reference = new RuntimeBeanReference(ref);
			pv = new PropertyValue(name, reference);
			beanDefination.addPropertyValue(pv);
		} else {
			return;
		}
	}

	private void parseCustomElement(Element element) {
		// TODO Auto-generated method stub
	}
}

beanFactory 接口包

BeanFactory 接口

  • 根据bean的名称去ioc容器中获取实例
public interface BeanFactory {

	Object getBean(String name);

	Object getBean(Class<?> type, String name);
}

AutowireCapableBeanFactory 接口继承BeanFactory

  • 具体负责BeanFactory的Bean实例的创建和装配
public interface AutowireCapableBeanFactory extends BeanFactory{

}

ListableBeanFactory 接口 继承BeanFactory

  • 具有列表化功能的Bean工厂
public interface ListableBeanFactory extends BeanFactory {

}

beanFactory.support 包

AbstractBeanFactory 类继承DefaultSingletonBeanRegistry 实现BeanFactory

  • 获取bean
  • 一个接口中同名方法设计重载时,更多的是为了更方便的给使用者使用
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {

	@Override
	public Object getBean(String name) {
		Object bean = doGetBean(name, null);
		return bean;
	}

	@Override
	public Object getBean(Class<?> type, String name) {
		Object bean = doGetBean(name, type);
		return bean;
	}

	private Object doGetBean(String name, Class<?> type) {
		// 先查询单例bean集合是否存在该bean实例
		Object singleton = getSingleton(name);
		// 有则直接返回
		if (singleton != null) {
			return singleton;
		}
		// 没有则需要查询BeanDefinition集合中是否存在该BeanDefinition
		BeanDefinition beanDefinition = getBeanDefinition(name);
		// 没有BeanDefinition则返回null
		if (beanDefinition == null) {
			return null;
		}
		// 有BeanDefinition则判断是单例还是多例
		if (beanDefinition.isSingleton()) {
			singleton = createBean(beanDefinition);

			addSingleton(name, singleton);
		} else if (beanDefinition.isPrototype()) {
			singleton = createBean(beanDefinition);
		}
		return singleton;
	}

	public abstract Object createBean(BeanDefinition beanDefinition);

	public abstract BeanDefinition getBeanDefinition(String name);
}

AbstractAutowireCapableBeanFactory 类继承AbstractBeanFactory 实现AutowireCapableBeanFactory 接口

  • 该工厂是负责Bean的创建和装配的
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {

	@Override
	public Object createBean(BeanDefinition beanDefinition) {
		// 实例化 new
		Object bean = createInstance(beanDefinition);
		if (bean == null)
			return null;
		// 属性填充 set
		populateBean(bean, beanDefinition);
		// 初始化 init
		initBean(bean, beanDefinition);
		return bean;
	}

	private void initBean(Object bean, BeanDefinition beanDefinition) {
		// TODO Aware接口会在此时被处理

		invokeInitMethod(bean, beanDefinition);
	}

	private void invokeInitMethod(Object bean, BeanDefinition beanDefinition) {
		// bean标签配置了init-method属性
		String initMethod = beanDefinition.getInitMethod();
		if (initMethod == null || initMethod.equals("")) {
			return;
		}
		ReflectUtils.invokeMethod(bean, initMethod);
		// TODO bean标签实现了InitializingBean接口
	}

	private void populateBean(Object bean, BeanDefinition beanDefinition) {
		List<PropertyValue> propertyValues = beanDefinition.getPropertyValues();
		for (PropertyValue pv : propertyValues) {
			String name = pv.getName();
			Object value = pv.getValue();
			Object valueToUse = null;
			if (value instanceof TypedStringValue) {
				TypedStringValue typedStringValue = (TypedStringValue) value;
				String stringValue = typedStringValue.getValue();
				Class<?> targetType = typedStringValue.getTargetType();
				if (targetType == String.class) {
					valueToUse = stringValue;
				} else if (targetType == Integer.class) {
					valueToUse = Integer.parseInt(stringValue);
				} // ....
			} else if (value instanceof RuntimeBeanReference) {
				RuntimeBeanReference reference = (RuntimeBeanReference) value;
				String ref = reference.getRef();

				// 创建一个bean的时候,根据依赖注入情况,自动去创建另一个bean去注入
				valueToUse = getBean(ref);
			}
			ReflectUtils.setProperty(bean, name, valueToUse);
		}
	}

	private Object createInstance(BeanDefinition beanDefinition) {
		// TODO 可以通过静态工厂去创建????
		// TODO 可以通过实例工厂去创建????

		try {
			String clazzName = beanDefinition.getClazzName();
			Class<?> clazzType = resolveClass(clazzName);
			Object bean = ReflectUtils.createObject(clazzType);

			return bean;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private Class<?> resolveClass(String clazzName) {
		try {
			Class<?> clazz = Class.forName(clazzName);
			return clazz;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
}

bena.registry 包

BeanDefinitionRegistry 接口

  • 提供对于BeanDefinition集合的访问
public interface BeanDefinitionRegistry {

	BeanDefinition getBeanDefinition(String name);

	void registerBeanDefinition(String name, BeanDefinition beanDefinition);
}

SingletonBeanRegistry 接口

  • 访问单例Bean实例集合的接口
public interface SingletonBeanRegistry {

	Object getSingleton(String name);

	void addSingleton(String name, Object bean);
}

bean.registry.support 包

DefaultSingletonBeanRegistry 实现了SingletonBeanRegistry 接口

  • bean实例集合
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

	// 只有单例的bean才需要放入Map集合中进行保存管理
	private Map<String, Object> singletonObjects = new HashMap<String, Object>();

	@Override
	public Object getSingleton(String name) {
		return this.singletonObjects.get(name);
	}

	@Override
	public void addSingleton(String name, Object bean) {
		this.singletonObjects.put(name, bean);
	}
}

DefaultListableBeanFactory 继承AbstractAutowireCapableBeanFactory 实现BeanDefinitionRegistry 接口

  • 封装xml中的bean标签表示的信息 -beanDefinition对象
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {

	
	private Map<String, BeanDefinition> beanDefinitions = new HashMap<String, BeanDefinition>();

	@Override
	public BeanDefinition getBeanDefinition(String name) {
		return this.beanDefinitions.get(name);
	}

	@Override
	public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
		this.beanDefinitions.put(name, beanDefinition);
	}
}

beanDefinition 包

BeanDefinition 类

  • 封装标签的信息
public class BeanDefinition {
	private String clazzName;//对应classname
	private String beanName;//对应 id
	private String initMethod;//对应 init-method
	//该信息是默认的配置,如果不配置就默认是singleton
	private String scope;//对应 scope

	private static final String SCOPE_SINGLETON = "singleton";
	private static final String SCOPE_PROTOTYPE = "prototype";

	/**
	 * bean中的属性信息
	 */
	private List<PropertyValue> propertyValues = new ArrayList<>();

	public BeanDefinition(String clazzName, String beanName) {
		this.beanName = beanName;
		this.clazzName = clazzName;
	}

	public String getBeanName() {
		return beanName;
	}

	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}

	public String getInitMethod() {
		return initMethod;
	}

	public void setInitMethod(String initMethod) {
		this.initMethod = initMethod;
	}

	public List<PropertyValue> getPropertyValues() {
		return propertyValues;
	}

	public void addPropertyValue(PropertyValue propertyValue) {
		this.propertyValues.add(propertyValue);
	}

	public String getClazzName() {
		return clazzName;
	}

	public void setClazzName(String clazzName) {
		this.clazzName = clazzName;
	}

	public String getScope() {
		return scope;
	}

	public void setScope(String scope) {
		this.scope = scope;
	}

	public void setPropertyValues(List<PropertyValue> propertyValues) {
		this.propertyValues = propertyValues;
	}

	public boolean isSingleton() {
		return SCOPE_SINGLETON.equals(this.scope);
	}

	public boolean isPrototype() {
		return SCOPE_PROTOTYPE.equals(this.scope);
	}
}

PropertyValue 类

  • 封装Property信息
public class PropertyValue {
	
	private String name;

	private Object value;

	public PropertyValue(String name, Object value) {
		super();
		this.name = name;
		this.value = value;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Object getValue() {
		return value;
	}

	public void setValue(Object value) {
		this.value = value;
	}
}
public class RuntimeBeanReference {

	private String ref;

	public String getRef() {
		return ref;
	}

	public void setRef(String ref) {
		this.ref = ref;
	}

	public RuntimeBeanReference(String ref) {
		super();
		this.ref = ref;
	}
}

TypedStringValue 类

  • 存储的是property标签的 value值
public class TypedStringValue {
	
	private String value;
	
	private Class<?> targetType;//value 的目标类型

	public TypedStringValue(String value) {
		this.value = value;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public Class<?> getTargetType() {
		return targetType;
	}

	public void setTargetType(Class<?> targetType) {
		this.targetType = targetType;
	}
}

userDao 包

UserDao 接口

public interface UserDao {

	List<User> queryUserList(String sqlId, Object param);
}

UserDaoImpl 类 实现UserDao 接口

  • 通过Bean实例查询数据库
public class UserDaoImpl implements UserDao {

	private DataSource dataSource;
	private Properties properties = new Properties();
	// 初始化方法
	public void init() {
		if (!properties.isEmpty()) {
			return;
		}
		try {
			InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("sqlmapping.properties");
			properties.load(inputStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public List<User> queryUserList(String sqlId, Object param) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet rs = null;

		try {
			connection = dataSource.getConnection();
			// 定义sql语句 ?表示占位符
			String sql = properties.getProperty("db.sql." + sqlId);

			System.out.println("SQL:" + sql);
			System.out.println("参数:" + param);
			// 获取预处理 statement
			preparedStatement = connection.prepareStatement(sql);

			// 设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的
			if (param instanceof Integer) {
				// ...
			} else if (param instanceof String) {
				preparedStatement.setObject(1, param.toString());
			} else {
				Class<?> clazz = param.getClass();
				String params = properties.getProperty("db.sql." + sqlId + ".paramnames");
				String[] paramArray = params.split(",");
				for (int i = 0; i < paramArray.length; i++) {
					String name = paramArray[i];
					Field field = clazz.getDeclaredField(name);
					field.setAccessible(true);
					Object value = field.get(param);
					preparedStatement.setObject(i + 1, value);

				}
			}

			// 向数据库发出 sql 执行查询,查询出结果集
			rs = preparedStatement.executeQuery();

			// 遍历查询结果集
			List<User> results = new ArrayList<User>();

			Class<?> clazz = User.class;
			while (rs.next()) {
				User instance = (User) clazz.newInstance();
				ResultSetMetaData metaData = rs.getMetaData();
				int columnCount = metaData.getColumnCount();
				for (int i = 0; i < columnCount; i++) {
					String columnName = metaData.getColumnName(i + 1);

					Field field = clazz.getDeclaredField(columnName);
					field.setAccessible(true);

					field.set(instance, rs.getObject(i + 1));
				}

				results.add(instance);
			}

			return results;
		} catch (

		Exception e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (preparedStatement != null) {
				try {
					preparedStatement.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (connection != null) {
				try {
					connection.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block e.printStackTrace();
				}
			}
		}
		return null;
	}
}

你可能感兴趣的:(#,SSM框架)