Java手写模拟IOC

SpringFramework--依赖注入模拟详解

为什么有依赖注入:平常的Java开发中,程序员在某个类中需要依赖其它类的方法。
我们通常是new一个依赖类再调用类实例的方法set进去,这种开发存在的问题是new的类实例不好统一管理。
所以Spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。
依赖注入的另一种说法是"控制反转"。通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员。
而控制反转是指new实例工作不由我们程序员来做而是交给Spring容器来做。

在这里为了使大家看的更加清晰我们用注解的方法去模拟:(注意:通过Spring创建的对象默认是单例)

首先给出两个注解类:

  1. Autowired注解类:用来注解依赖类成员,表示该成员需要注入;
  2. Component注解类:用来注解哪个类里面有成员有Atuowired注解;
Autowired 类
package com.htt.spring_imitate.annotation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(FIELD)
public @interface Autowired {
	String name() default "";
}

Componet 类
package com.htt.spring_imitate.annotation;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(TYPE)
public @interface Component {
	String name() default "";
}

此时我们要给出一个类BeanDefinition:此类是用来产生一个Bean(即一个平凡类)的实例对象的;

package com.htt.spring_imitate.core;

public class BeanDefinition {
	private Class<?> klass;
	private Object object;
//      确定此类是否已近被注入过
	private boolean inject;
	
	protected Class<?> getKlass() {
		return klass;
	}
	
	protected void setKlass(Class<?> klass) {
		this.klass = klass;
	}
	
	protected Object getObject() {
		return object;
	}
	
	protected void setObject(Object object) {
		this.object = object;
	}

	protected boolean isInject() {
		return inject;
	}

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

	@Override
	public String toString() {
		return "[klass=" + klass.getSimpleName() + ", object=" + object + "]";
	}
	
	
}

接下来就可以去建造一个模拟的Spring工厂BeanFactory,可以根据Class类得到一个实例对象(如果这个类中有还未注入的,会自动注入)。这个BeanFactory采用懒汉模式即等到相关Bean被获取后才去注入。

(其中包扫描的技术可以看这个链接包扫描技术  )

其中可以通过两种方法得到实例对象,我们给的返回值均为泛型类型

  1. public <T> T getBean(String className) ;
  2. public <T> T getBean(Class<?> className);
package com.htt.spring_imitate.core;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.HTT.Util.PackageScanner;
import com.htt.spring_imitate.annotation.Autowired;
import com.htt.spring_imitate.annotation.Bean;
import com.htt.spring_imitate.annotation.Component;
import com.htt.spring_imitate.exception.HasNoBeanException;

public class BeanFactory {
        //用来存放对象实例的一个静态map(键为ClassName的字符串,值为BeanDefinition的一个实例)
	private static final Map<String, BeanDefinition> beanPool;
	
	static {
		beanPool = new HashMap<String, BeanDefinition>();
	}
		
	public BeanFactory() {
	}
	
//      包扫描(扫描那个包下哪些对象需要注入)
	public static void scanBeanByPackage(String packageName) {
		new PackageScanner() {
			
			@Override
			public void dealClass(Class<?> klass) {
				if (klass.isPrimitive()
					|| klass.isArray()
					|| klass.isEnum()
					|| klass.isAnnotation()
					|| klass.isInterface()
					|| !klass.isAnnotationPresent(Component.class)) {
					return ;
				}
				Object object = null;
				try {    
                                        //通过类名用反射机制得到一个实例(但里面的成员为null)
					object = klass.newInstance();
					BeanDefinition bd = new BeanDefinition();
					bd.setKlass(klass);
					bd.setObject(object);
					
					beanPool.put(klass.getName(), bd);
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}.packageScanner(packageName);
	}
	private void injectProperties(BeanDefinition bd) {
		System.out.println("注入");
		Class<?> klass = bd.getKlass();
		Object object = bd.getObject();
		System.out.println(klass);
		Field[] fileds = klass.getDeclaredFields();
		for (Field field : fileds) {
			if (!field.isAnnotationPresent(Autowired.class)) {
				continue;
			}
			// TODO 应该先对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 (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		bd.setInject(true);
	}
	
	@SuppressWarnings({ "null", "unchecked" })
	public <T> T getBean(String className) {
		BeanDefinition bd = getBeanDefinition(className);
		if (bd == null) {
			throw new HasNoBeanException("类["
					+ className +  "]没有对应的Bean");
		}
		Object object = bd.getObject();
		//以防再次注入
		if (!bd.isInject()) {
			injectProperties(bd);
		}
		
		return (T) object;
	}
	
	public <T> T getBean(Class<?> className) {
		return getBean(className.getName());
	}
	
	BeanDefinition getBeanDefinition(String className) {
		return beanPool.get(className);
	}
	
	BeanDefinition getBeanDefinition(Class<?> className) {
		return beanPool.get(className.getName());
	}
}

其中有一种情况可能出现循环依赖(比如A类有成员B,B类有成员A)如果getBean(A.class)会出现这样的循环,我们这里采用的形式是给BeanDefinition类一个成员boolean inject;它不仅仅可以判断是否注入,也可以处理循环依赖,我们可以先给A的BeanDefinition的inject为true;在B的成员BeanDefinition的inject里判断时可以结束循环依赖。

下面我们给一个Test类来测试一下:("com.htt.spring_imitate.some_class"这个包的东西在后面给出)

package com.htt.spring_imitate.test;

import com.htt.spring_imitate.core.BeanFactory;
import com.htt.spring_imitate.some_class.ClassOne;

public class Test{

	public static void main(String[] args) {
//              扫描这个包下面类
		BeanFactory.scanBeanByPackage("com.htt.spring_imitate.some_class");
		
		BeanFactory beanFactory = new BeanFactory();
		ClassOne co1 = beanFactory.getBean(ClassOne.class);
		ClassOne co2 = beanFactory.getBean(ClassOne.class);
		System.out.println(co1);
		System.out.println(co2);
		
		System.out.println("判断是不是单例模式" + (co1 == co2));
	}

}

结果如下:

ClassOne 类
package com.htt.spring_imitate.some_class;

import com.htt.spring_imitate.annotation.Autowired;
import com.htt.spring_imitate.annotation.Component;

@Component
public class ClassOne {
	@Autowired
	private Complex complex;
	private Point point;
	private String str;
	
	public ClassOne() {
	}

	public Complex getComplex() {
		return complex;
	}

	public void setComplex(Complex complex) {
		this.complex = complex;
	}

	public Point getPoint() {
		return point;
	}

	public void setPoint(Point point) {
		this.point = point;
	}

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

	@Override
	public String toString() {
		return "[complex=" + complex + ", str=" + str 
				+ ", point=" + point + "]";
	}
	
}


Complex 类
package com.htt.spring_imitate.some_class;

import com.htt.spring_imitate.annotation.Component;

@Component
public class Complex {
		private double real;
		private double vir;
		
		public Complex() {
		}

		public double getReal() {
			return real;
		}

		public void setReal(double real) {
			this.real = real;
		}

		public double getVir() {
			return vir;
		}

		public void setVir(double vir) {
			this.vir = vir;
		}

		@Override
		public String toString() {
			return "(" + real + ", " + vir + ")";
		}

	}
扫描二维码关注公众号,回复: 11348991 查看本文章

猜你喜欢

转载自blog.csdn.net/baidu_41922630/article/details/102545102
今日推荐