Spring框架——IOC模拟实现(基于注解方式)

在前面的文章中我们讲述了Spring的基本概念和及IOC和AOP在这篇文章中我们来模拟实现Spring的IOC操作
(1)关于模拟实现IOC我们主要实现两个功能

  1. 控制反转:用框架来创建对象
 @Test
    public void testService(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");
        UserService userservice = context.getBean("userService", UserService.class);
        userservice.add();
    }
  1. 依赖注入:用框架来注入属性
@Component(singleton = false)
public class ClassOne {
	@Autowired
	private Complex complex;
	@Autowired
	private Point point;
}

(2)实现原理

  1. 控制反转:构建一个容器(上下文),在使用框架前,先扫描工程所有的类,看其是否需要通过框架生成对象(给类加Component注解)。如果是则在这个容器中存储类及其对象;在用框架创建这些类的对象时,基本上都是从这个容器中获取的;这些类的属性,若其类型也在容器中,则,它们将被自动初始化,且用容器中的对象完成初始化。判断哪些类可以放置在容器容有两种方式,注解或XML配置文件。本次实现使用注解方式。
  2. 在实现控制反转时设置对象是单例,或是非单例,可以在Component注解中加singleton参数实现。如果是单例,则在扫描包时生成对象,否则在getBean时生成
  3. 依赖注入:在类的属性上添加Autowired注解,判断其是否需要自动注入,如果是,则从容器中获取该属性的对象对其注入。
  4. 在注入的时候,可能会出现循环依赖,这个问题可以通过在注入属性前将inject设为true打破这个循环得以解决。
    Component注解
@Retention(RUNTIME)
@Target(TYPE)
public @interface Component {
	boolean singleton() default true;//默认储存单例对象
}

Autowired注解

@Retention(RUNTIME)
@Target({ FIELD, METHOD })
public @interface Autowired {
}

(3)代码实现

  1. BeanDefinition:类的模型, 包含类的元数据类,类的对象,是否单例和是否需要注入
public class BeanDefinition {
	private Class<?> klass;
	private Object object;
	private boolean singleton;
	private boolean inject;
	
	BeanDefinition() {
		this.inject = false;
		this.singleton = true;
	}

	boolean isSingleton() {
		return singleton;
	}

	void setSingleton(boolean singleton) {
		this.singleton = singleton;
	}

	boolean isInject() {
		return inject;
	}

	void setInject(boolean inject) {
		this.inject = inject;
	}

	Class<?> getKlass() {
		return klass;
	}

	void setKlass(Class<?> klass) {
		this.klass = klass;
	}

	Object getObject() {
		return object;
	}

	void setObject(Object object) {
		this.object = object;
	}
	
}
  1. BeanFactory:核心类,扫描指定包,获取需要放入容器(beanpool)的类(bean)
public class BeanFactory {
		//容器
		private static final Map<String, BeanDefinition> beanPool;
		static {
			beanPool = new HashMap<String, BeanDefinition>();
		}
		
		public BeanFactory() {
		}
		//包扫描
		public void scanBeanByPackage(String packageName) {
			new PackageScanner() {
				@Override
				//得到带有Component的类
				public void dealClass(Class<?> klass) {
					if (klass.isPrimitive()
							|| klass.isInterface()
							|| klass.isAnnotation()
							|| klass.isEnum()
							|| klass.isArray()
							|| !klass.isAnnotationPresent(Component.class)) {
						return;
					}
					try {
					    //生成类对象,并放入容器中
					    Object object = null;
						Component component = klass.getAnnotation(Component.class);
						boolean singleton = component.singleton();
						
						BeanDefinition beanDefinition = new BeanDefinition();
						if (singleton) {
							object = klass.newInstance();
						}

						beanDefinition.setSingleton(singleton);
						beanDefinition.setKlass(klass);
						beanDefinition.setObject(object);
						
						beanPool.put(klass.getName(), beanDefinition);
					} catch (InstantiationException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}.scanPackage(packageName);
		}
			
		BeanDefinition getBeanDefinition(String klassName) {
			return beanPool.get(klassName);
		}
		BeanDefinition getBeanDefinition(Class<?> klass) {
			return getBeanDefinition(klass.getName());
		}
		
		private void injectProperties(BeanDefinition beanDefinition) throws RuntimeException {
			Class<?> klass = beanDefinition.getKlass();
			Object object = beanDefinition.getObject();
			
			Field[] fields = klass.getDeclaredFields();
			for (Field field : fields) {
				if (!field.isAnnotationPresent(Autowired.class)) {
					continue;
				}
				// 应该先对inject进行判断,若为true,表示该对象已经完成注入;
				// 这种方法可以避免循环依赖。
				field.setAccessible(true);
				Object value = getBean(field.getType());
				if (value == null) {
					throw new HasNoBeanException("类[" + klass.getName()
							+ "]的[" + field.getName()
							+ "]成员没有对应的Bean!");
				}
				try {
					field.set(object, value);
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
		
		private static BeanDefinition getBeanObject(String className) {
			BeanDefinition bean = beanPool.get(className);
			if (bean == null) {
				return null;
			}
			Object object = null;
			if (!bean.isSingleton()) {
				Class<?> klass = bean.getKlass();
				try {
					object = klass.newInstance();
					bean.setObject(object);
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
			
			return bean;
		}
		
		@SuppressWarnings("unchecked")
		public <T> T getBean(String klassName) throws RuntimeException {
			BeanDefinition bean = getBeanObject(klassName);
			if (bean == null) {
				System.out.println("Bean[" + klassName + "]不存在!");
				return null;
			}
			Object object = bean.getObject();
			
			if (!bean.isInject() || !bean.isSingleton()) {
				bean.setInject(true);
				// 这里完成对object中需要注入的成员的初始化工作!
				injectProperties(bean);
			}
			
			return (T) object;
		}
		
		public <T> T getBean(Class<?> klass) throws RuntimeException {
			return getBean(klass.getName());
		}
		
	}




(4)测试

  1. 默认单例的控制反转
@Component
public class ClassOne {
	public ClassOne() {
		System.out.println("ClassOne...");
	}
}
public class Demo {
	public static void main(String[] args) {
		BeanFactory beanFactory = new BeanFactory();
		beanFactory.scanBeanByPackage("some_class");
		
		ClassOne classOne = beanFactory.getBean(ClassOne.class);
	}
}

在这里插入图片描述
2. 非单例控制反转

@Component(singleton = false)
public class ClassOne {
	public ClassOne() {
		System.out.println("ClassOne...");
	}
	
}
public class Demo {
	public static void main(String[] args) {
		BeanFactory beanFactory = new BeanFactory();
		beanFactory.scanBeanByPackage("some_class");
		
		ClassOne classOne = beanFactory.getBean(ClassOne.class);
		System.out.println("classOne-->" + classOne + "classOne.hashCode()-->" + classOne.hashCode());
		ClassOne classOne2 = beanFactory.getBean(ClassOne.class);
		System.out.println("classOne2-->" + classOne2 + "classOne2.hashCode-->" + classOne2.hashCode());
	}
}

Spring框架——IOC模拟实现(基于注解方式)_第1张图片

  1. 注入属性
@Component
public class ClassTwo {
	public ClassTwo() {
		System.out.println("ClassTwo...");
	}
	@Autowired
	public ClassOne classone;
	
}

public class Demo {

	public static void main(String[] args) {
		BeanFactory beanFactory = new BeanFactory();
		beanFactory.scanBeanByPackage("some_class");
		
		ClassTwo classtwo = beanFactory.getBean(ClassTwo.class);
	}

}

在这里插入图片描述

  1. 循环依赖的属性注入
@Component
public class ClassTwo {
	public ClassTwo() {
		System.out.println("ClassTwo...");
	}
	@Autowired
	public ClassOne classone;
	
}
@Component(singleton = false)
public class ClassOne {
	public ClassOne() {
		System.out.println("ClassOne...");
	}
	
	@Autowired
	public ClassTwo classtwo;
	
}

public class Demo {

	public static void main(String[] args) {
		BeanFactory beanFactory = new BeanFactory();
		beanFactory.scanBeanByPackage("some_class");
		
		ClassTwo classtwo = beanFactory.getBean(ClassTwo.class);
	}

}

Spring框架——IOC模拟实现(基于注解方式)_第2张图片

你可能感兴趣的:(java,spring)