您的位置:首页 > 编程语言 > Java开发

通俗谈 Spring IOC ,自己动手实现简版IOC

2018-01-18 22:05 239 查看
因为要面试JAVA岗工程师,对Spring 的IOC 原理还是必须明确的,所以就花了点时间自己认真摸索了下。
Spring IOC (Inversion Of Control),控制反转。想起初学IOC的时候,一头雾水,什么是IOC?
通俗的讲:就是本来应该有程序员自己new 一个对象,但是现在你不需要new 了,而是框架帮你new 了对象。这种对象的创建(其他管理)权利的给了框架,就被称为IOC(控制反转)。看到这里大家应该清楚了很多。
下面我通过自己代码实现了Spring IOC 中我们常用的@Autowrid 和@Service(通过标签自动注入对象),和IOC中的BeanFactory 对配置文件中的bean进行管理。

一.通过标签进行自动注入对象(一般是在service 中自动诸如Dao 对象)。
代码如下:
1.MyService标签类(模仿@Service):
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

@Target({ElementType.TYPE})//类

@Retention(RetentionPolicy.RUNTIME)//运行时

public @interface MyService {

}


2.MyAutoWrid 标签类(模仿@Autowrid):
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

@Target(ElementType.FIELD)//方法
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAutoWrid {

}

3.service 接口:

public interface PriceService {

void show_price();

}
4.service接口实现(主角1 打上了我们自定义的标签,自动注入一个对象):
@MyService
public class PriceServiceImpl implements PriceService {

@MyAutoWrid
Price_getter price_getter; // 自动注入一个对象

public void show_price() {

price_getter.show_price();

}

}5.Dao类(假装从数据库获取了数据):
public class Price_getter {

//假装从数据库读取数据
void show_price(){

System.out.println("你的价格是5元!!!!");

}

}
6.注入对象的工具类:
import java.lang.reflect.Field;

public class Fill_varlible_Tool {

//注入Dao对象后的service
public Object finsh_object;

//对标签进行解析,并且通过反射实现对象,并将其赋值给service
public void fill_Object(Object target) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

//获取需要自动注入对象的类
Class<?> fatherclazz=target.getClass();

//判断该类是否有Myservice标签
if(fatherclazz.isAnnotationPresent(MyService.class)){

//获取该类的所有属性
Field[] fields=fatherclazz.getDeclaredFields();

for(Field item:fields){

//判断属性是否带有标签 MyAutoWrid
if(item.isAnnotationPresent(MyAutoWrid.class)){

//反射获取该类,实例化对象并且赋值给对应的属性
Class<?> subclazz=Class.forName(item.getType().getName(),false,Thread.currentThread().getContextClassLoader());

item.set(target,subclazz.newInstance());

finsh_object=target;
}
}
}

}

//返回注入后的对象
public Object getFinsh_object() {
return finsh_object;
}
}
7.初始化容器类:
//初始化容器类
public class InitContainer {

//模拟web程序启动的时候,对传入的service 进行注入对象
public Object init(Object object) throws IllegalAccessException, InstantiationException, ClassNotFoundException {

Fill_varlible_Tool tool=new Fill_varlible_Tool();
tool.fill_Object(object);
return tool.getFinsh_object();
}

}
8.测试类(模拟应用启动):
public class MainTest {

public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, InstantiationException {

InitContainer container=new InitContainer();

//本应该扫描获取有标记 MyService的class 并且new 出他们的对象
PriceServiceImpl priceService=new PriceServiceImpl();

//通过容器初始化对他们的Dao 属性进行自动赋值
priceService=(PriceServiceImpl) container.init(priceService);

priceService.show_price();

}

}
9.运行结果:
你的价格是5元!!!!

Process finished with exit code 0

二.通过配置文件,使用BeanFactory 管理bean的IOC。

1.MyBeanFactory类(模拟BeanFactory):
public interface MyBeanFactory {

Object getbean(String id);

}
2.实现MyBeanFactory:
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.HashMap;
import java.util.List;

public class MyBeanFactoryImpl implements MyBeanFactory {

private HashMap<String, Object> mymap = new HashMap<String, Object>();

public MyBeanFactoryImpl(String filename) throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException {

SAXReader saxReader = new SAXReader();

Document document = saxReader.read(new File(filename));

List<Element> elements = document.selectNodes("/beans/bean");

for (Element item : elements) {

String id = item.attributeValue("id");
String class_val = item.attributeValue("class");

Object object=Class.forName(class_val).newInstance();
mymap.put(id,object);
}

}

public Object getbean(String id) {
return mymap.get(id);
}

}
3.一般接口 Skill:
public interface Skill {

void show_myskill();
}
4.实现Skill接口的Programmer类:
public class Programmer implements Skill {

public void show_myskill() {
System.out.println("编程写软件");
}
}5.实现Skill接口的Doctor类:
public class Doctor implements Skill{

public void show_myskill() {
System.out.println("看病救人");
}
}
6.定义bean的配置文件  applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="d" class="SpringIoc_xml.Doctor"></bean>
    <bean id="p" class="SpringIoc_xml.Programmer"></bean>
</beans>

7.测试类Test(模拟应用启动):
import org.dom4j.DocumentException;

public class Test_XMl {

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, DocumentException, IllegalAccessException {

MyBeanFactory myBeanFactory=new MyBeanFactoryImpl("C:\\Users\\Administrator\\Desktop\\applicationContext.xml");

Skill skill= (Skill) myBeanFactory.getbean("d");
skill.show_myskill();

Skill skill2= (Skill) myBeanFactory.getbean("p");
skill2.show_myskill();

}
}8.运行结果:
看病救人
编程写软件

Process finished with exit code 0

这些是我对Spring 的IOC的理解和简单实现,如果有不对的地方,恳请批评指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息