实现简单IOC和AOP容器

AOP思想的实现方法一般是代理模式。jdk只支持接口的代理,而对于类的代理,Spring支持了CGLIB,AspectJ动态代理。

IOC的实现原理是反射。

如果我们要做一个简单的IOC容器。

首先实现简单的四步:

1.扫描xml配置文件。

2.遍历所有的bean节点。读取id和class属性

3.遍历bean节点下每个property节点的name和value或ref值。将值注入到属性中

4.将加载的bean注入到容器中

为了实现上述功能,创建如下几个类:

springIOC     ioc的实现类

springIOCTest  ioc测试类

car  汽车实体类

wheel 车轮实体类

ioc.xml ioc配置文件

springIOC类:

package SpringIOC;

import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SpringIOC {
    private Map<String, Object> map = new HashMap<>();
    
    public SpringIOC(String xmlName) throws Exception{
        loadbean(xmlName);
    }
    
    public Object getbean(String beanName){
        Object bean = map.get(beanName);
        if(bean == null){
            throw new IllegalArgumentException();
        }
        return bean;
    }
    private void registerBean(String id, Object bean) {
         map.put(id, bean);
        }
    public void loadbean(String xmlName) throws Exception{
        FileInputStream fileInputStream = new FileInputStream(xmlName);
        DocumentBuilderFactory factory  = DocumentBuilderFactory.newInstance();
        DocumentBuilder newDocumentBuilder = factory.newDocumentBuilder();
        Document Document = newDocumentBuilder.parse(fileInputStream);
        Element root = Document.getDocumentElement();
        NodeList childNodes = root.getChildNodes();
        for(int i =0;i<childNodes.getLength();i++){
            Node node = childNodes.item(i);
            if(node instanceof Element){
                Element element = (Element)node;
                String id = element.getAttribute("id");
                String className = element.getAttribute("class");
                Class<?> beanClass  = null;
                try {
                    beanClass = Class.forName(className);
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }
                
                Object bean = beanClass.newInstance();
                //解析property属性值,并注入
                NodeList propertyList = element.getElementsByTagName("property");
                for(int j=0;j<propertyList.getLength();j++){
                    Node propertyItem = propertyList.item(j);
                    if(propertyItem instanceof Element){
                        Element property = (Element)propertyItem;
                        String name = property.getAttribute("name");
                        String value = property.getAttribute("value");
                        //利用反射机制将类的内部属性变为可访问的
                        Field filed = bean.getClass().getDeclaredField(name);
                        filed.setAccessible(true);if(value != null && value.length()>0){
                            filed.set(bean, value);
                        }else{
                            String ref = property.getAttribute("ref");
                            if (ref == null || ref.length() == 0) {
                                throw new IllegalArgumentException("ref config error");
                            }
                            filed.set(bean, getbean(ref));
                        }
                    }
                }
                registerBean(id, bean);
            }
        }
    }
}

由此可知IOC的实现原理是反射。

springIOCtext类:

package SpringIOC;

public class SpringIOCTest {
    public static void main(String[] args) throws Exception {
        SpringIOC springIOC = new SpringIOC("C:/file/Workspaces/StringTest/bin/SpringIOC/ioc.xml");
        Car car = (Car)springIOC.getbean("car");
        Wheel wheel = (Wheel)springIOC.getbean("wheel");
        System.out.println(car);
        System.out.println(wheel);
    }
}

实体类和ioc.xml:

package SpringIOC;

public class Car {
    private String Carbrand;
    private Wheel wheel;
    public String getCarbrand() {
        return Carbrand;
    }
    public void setCarbrand(String carbrand) {
        Carbrand = carbrand;
    }
    public Wheel getWheel() {
        return wheel;
    }
    public void setWheel(Wheel wheel) {
        this.wheel = wheel;
    }
    

    @Override
    public String toString() {
        return "Car [Carbrand=" + Carbrand + ", wheel=" + wheel + "]";
    }
}
package SpringIOC;

public class Wheel {
    private String wheelBrand;
    private String width;
    private String height;
    public String getWheelBrand() {
        return wheelBrand;
    }
    public void setWheelBrand(String wheelBrand) {
        this.wheelBrand = wheelBrand;
    }
    public String getWidth() {
        return width;
    }
    public void setWidth(String width) {
        this.width = width;
    }
    public String getHeight() {
        return height;
    }
    public void setHeight(String height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Wheel [wheelBrand=" + wheelBrand + ", width=" + width + ", height=" + height + "]";
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<beans>
    <bean id="wheel" class="SpringIOC.Wheel">
        <property name="wheelBrand" value="米其林">
        </property>
        <property name="width" value="50">
        </property>
        <property name="height" value="50">
        </property>
    </bean>
    <bean id="car" class="SpringIOC.Car">
        <property name="Carbrand" value="奔驰">
        </property>
        <property name="wheel" ref="wheel">
        </property>
    </bean>
</beans>

这里就简单的IOC容器的实现,运行结果:

Car [Carbrand=奔驰, wheel=Wheel [wheelBrand=米其林, width=50, height=50]]
Wheel [wheelBrand=米其林, width=50, height=50]

但是最简陋的IOC容器,随便考虑一下就还有非常多需要改进的地方还有非常的多

猜你喜欢

转载自www.cnblogs.com/jinsheng1027/p/12131497.html