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容器,随便考虑一下就还有非常多需要改进的地方还有非常的多