准备两个类
@Data
public class HelloIoc {
private int age;
private String name;
private User user;
public void sayHello(){
System.out.println("my name is"+name);
}
}
@Data
public class User {
private int age;
private String name;
private String work;
private HelloIoc helloIoc;
public void sayHi(){
System.out.println("我叫"+name);
}
}
然后,准备一个XML文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="HelloIoc" class="org.example.pojo.HelloIoc">
<property name="name" value="jeysin"/>
<property name="age" value="13"/>
</bean>
<bean id="user" class="org.example.pojo.User">
<property name="name" value="yize"/>
<property name="age" value="13" />
</bean>
</beans>
对XML文件进行解析
读取xml文件的接口
public interface BeanDefinitonReader {
void loadBeanDefiniton(Resource resource) throws ParserConfigurationException, IOException, SAXException, ClassNotFoundException;
}
实现类:
package org.example.Resouce;
import org.example.Bean.BeanDefiniton;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.swing.text.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author Clive
* @date 2020/9/17 0017 10:34
*/
public class DefaultBeanDefinitonReader implements BeanDefinitonReader {
private final Map<String, BeanDefiniton> beanDefinitonMap=new HashMap<>();
public DefaultBeanDefinitonReader(Resource resource) throws ParserConfigurationException, IOException, SAXException, ClassNotFoundException {
loadBeanDefiniton(resource);
}
@Override
public void loadBeanDefiniton(Resource resource) throws ParserConfigurationException, IOException, SAXException, ClassNotFoundException {
InputStream inputStream=null;
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
inputStream = resource.getInputStream();
org.w3c.dom.Document document = documentBuilder.parse(inputStream);
registerBeanDefinitons(document);
inputStream.close();
}
public void registerBeanDefinitons(org.w3c.dom.Document document) throws ClassNotFoundException {
Element rootElement = document.getDocumentElement();
NodeList childNodes = rootElement.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element){
Element element = (Element) node;
String beanId = element.getAttribute("id");
String beanClass = element.getAttribute("class");
BeanDefiniton beanDefiniton = new BeanDefiniton(beanClass);
beanDefiniton.setBeanClass(Class.forName(beanClass));
processProperties(element,beanDefiniton);
beanDefinitonMap.put(beanId,beanDefiniton);
}
}
}
public void processProperties(Element beanNode,BeanDefiniton beanDefiniton){
NodeList childNodes = beanNode.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element){
Element element = (Element) node;
String fieldName = element.getAttribute("name");
String fieldValue = element.getAttribute("value");
if (null!=fieldValue && fieldValue.length()>0){
beanDefiniton.setBeanMaps(fieldName,fieldValue);
}
else{
String ref = element.getAttribute("ref");
beanDefiniton.setBeanMaps(fieldName,new BeanRef(ref));
}
}
}
}
public Map<String, BeanDefiniton> getBeanDefinitonMap() {
return beanDefinitonMap;
}
}
读取Resource的接口
public interface Resource {
public InputStream getInputStream() ;
}
实现类:
public class UrlResource implements Resource {
private String configLocation;
@Override
public InputStream getInputStream() {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(configLocation);
return resourceAsStream;
}
public UrlResource(String configLocation) {
this.configLocation = configLocation;
}
}
解决循环依赖,把Ref的类存起来
package org.example.Resouce;
/**
* @author Clive
* @date 2020/9/17 0017 10:27
*/
public class BeanRef {
private String BeanRef;
public BeanRef(String beanRef) {
BeanRef = beanRef;
}
public String getBeanRef() {
return BeanRef;
}
}
解析出来的数据存放在BeanDifinition类中
package org.example.Bean;
import lombok.Data;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Clive
* @date 2020/9/17 0017 10:13
*/
public class BeanDefiniton {
private Object bean;
private Class beanClass;
private String beanClassName;
private ConcurrentHashMap<String,Object> beanMaps =new ConcurrentHashMap<String, Object>();
public ConcurrentHashMap<String, Object> getEarlyBeanMaps() {
return earlyBeanMaps;
}
public void setEarlyBeanMaps(String name,Object s) {
earlyBeanMaps.put(name,s);
}
private ConcurrentHashMap<String,Object> earlyBeanMaps =new ConcurrentHashMap<String, Object>();
public BeanDefiniton(String beanClassName) {
this.beanClassName = beanClassName;
}
public Object getBean() {
return bean;
}
public void setBean(Object bean) {
this.bean = bean;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
}
public ConcurrentHashMap<String, Object> getBeanMaps() {
return beanMaps;
}
public void setBeanMaps(String fieldName, Object fieldValue) {
beanMaps.put(fieldName,fieldValue);
}
}
工厂类的接口
/**
* @author Clive
* @date 2020/9/17 0017 11:15
*/
public interface BeanFactory {
Object getBean(String name) throws NoSuchFieldException, IllegalAccessException;
public void registerBeanDefiniton(String beanName,BeanDefiniton beanDefiniton);
}
实现类:
package org.example.Bean;
import org.example.Resouce.BeanRef;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Clive
* @date 2020/9/17 0017 11:17
*/
public class DefaultAutowireFactory implements BeanFactory {
private ConcurrentHashMap<String, BeanDefiniton> beanMaps=new ConcurrentHashMap<>();
@Override
public Object getBean(String name) throws NoSuchFieldException, IllegalAccessException {
BeanDefiniton beanDefiniton = beanMaps.get(name);
Object bean = beanDefiniton.getBean();
if (null==bean){
bean=doCreateBean(beanDefiniton);
}
return bean;
}
@Override
public void registerBeanDefiniton(String beanName, BeanDefiniton beanDefiniton) {
beanMaps.put(beanName,beanDefiniton);
}
public Object doCreateBean(BeanDefiniton beanDefiniton) throws NoSuchFieldException, IllegalAccessException {
Object bean=null;
try {
bean = beanDefiniton.getBeanClass().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
beanDefiniton.setBean(bean);
applyPropertyValue(bean,beanDefiniton.getBeanMaps());
return bean;
}
public void applyPropertyValue(Object bean, Map<String,Object> propertyMap) throws NoSuchFieldException, IllegalAccessException {
Set<Map.Entry<String, Object>> entries = propertyMap.entrySet();
for (Map.Entry<String,Object> entry:
entries) {
Field declaredField = bean.getClass().getDeclaredField(entry.getKey());
declaredField.setAccessible(true);
Object value = entry.getValue();
if(value instanceof BeanRef){
declaredField.set(bean, getBean(((BeanRef) value).getBeanRef()));
}else {
String type = declaredField.getType().getName();
if (type.equals("java.lang.String")){
declaredField.set(bean,(String)value);
}else if (type.equals("java.lang.integer")||type.equals("int")){
declaredField.set(bean,Integer.valueOf((String) value));
}
}
}
}
}
设计一个ApplicationContext类,进行bean的初始化
package org.example.Bean;
/**
* @author Clive
* @date 2020/9/17 0017 12:53
*/
public interface ApplicationContext {
Object getBean(String beanName) throws NoSuchFieldException, IllegalAccessException;
}
实现类:
package org.example.Bean;
import org.example.Resouce.DefaultBeanDefinitonReader;
import org.example.Resouce.UrlResource;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.Map;
/**
* @author Clive
* @date 2020/9/17 0017 12:55
*/
public class ClassPathXmlApplicationContext implements ApplicationContext {
private String configLocation;
private BeanFactory beanFactory;
private static ClassPathXmlApplicationContext context;
private ClassPathXmlApplicationContext() throws ParserConfigurationException, SAXException, IOException {
this.beanFactory=new DefaultAutowireFactory();
}
public static ClassPathXmlApplicationContext newInstance() throws IOException, SAXException, ParserConfigurationException {
if(context==null){
context=new ClassPathXmlApplicationContext();
}
return context;
}
public void setConfigLocation(String configLocation) throws ParserConfigurationException, SAXException, IOException, ClassNotFoundException {
this.configLocation = configLocation;
refresh();
}
@Override
public Object getBean(String beanName) throws NoSuchFieldException, IllegalAccessException {
return beanFactory.getBean(beanName);
}
public void refresh() throws IOException, SAXException, ParserConfigurationException, ClassNotFoundException {
DefaultBeanDefinitonReader reader = new DefaultBeanDefinitonReader(new UrlResource(configLocation));
for (Map.Entry<String, BeanDefiniton> entry :
reader.getBeanDefinitonMap().entrySet()) {
this.beanFactory.registerBeanDefiniton(entry.getKey(), entry.getValue());
}
}
}
最后测试一下
package org.example;
import static org.junit.Assert.assertTrue;
import org.example.Bean.ApplicationContext;
import org.example.Bean.ClassPathXmlApplicationContext;
import org.example.pojo.HelloIoc;
import org.example.pojo.User;
import org.junit.Test;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
@Test
public void test() throws NoSuchFieldException, IllegalAccessException, ParserConfigurationException, SAXException, IOException, ClassNotFoundException {
ClassPathXmlApplicationContext classPathXmlApplicationContext = ClassPathXmlApplicationContext.newInstance();
classPathXmlApplicationContext.setConfigLocation("application.xml");
User user = (User) classPathXmlApplicationContext.getBean("user");
user.sayHi();
HelloIoc helloIoc = (HelloIoc) classPathXmlApplicationContext.getBean("HelloIoc");
helloIoc.sayHello();
}
}