平常的Java开发中,程序员在某个类中需要依赖其它类的方法。我们通常是new一个依赖类再调用类实例的方法set进去,这种开发存在的问题是new的类实例不好统一管理。所以Spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。
依赖注入的另一种说法是"控制反转"。通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员而控制反转是指new实例工作不由我们程序员来做而是交给Spring容器来做。
注意在这篇文章中我们用注解的方法去模拟,采用懒加载方式。
其中涉及到一个扫描包中其他Java类的扫描工具类
模拟的思路如下:
package 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 "";
}
package 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 "";
boolean isSinglton() default true;
}
package annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 如果要向接口注入,需要确定注入接口实现类的哪一个
* @author quan
* @create 2020-06-25 12:52
*/
@Retention(RUNTIME)
@Target(FIELD)
public @interface Qualifier {
String ImplementationClass() default "";
}
package core;
/**
* 类的定义
*/
public class BeanDefinition {
private Class<?> klass;
private Object object;
private boolean inject;
public BeanDefinition() {
}
protected Class<?> getKlass() {
return klass;
}
protected void setKlass(Class<?> klass) {
this.klass = klass;
}
protected Object getObject() {
return object;
}
protected Object getPropertyObject() throws IllegalAccessException, InstantiationException {
return klass.newInstance();
}
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 + "]";
}
}
package core;
import annotation.Autowired;
import annotation.Component;
import annotation.Qualifier;
import exception.HasNoBeanException;
import exception.InJectFailException;
import util.PackageScanner;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* 拥有三大功能
* 1.scanBeanByPackage:启动容器
* 2.injectproperties:依赖注入
* 3.getbean:获得实例
*/
public class BeanFactory {
private final Map<Class<?>, BeanDefinition> beanPool;
private final Map<String, Class<?>> alias;
static {
}
public BeanFactory() {
beanPool = new HashMap<Class<?>, BeanDefinition>();
alias = new HashMap<String, Class<?>>();
}
public 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 {
Component component = klass.getAnnotation(Component.class);
String alia = component.name();
if (alias.size() == 0) {
alia = klass.getSimpleName();
}
alias.put(alia, klass);
object = klass.newInstance();
BeanDefinition bd = new BeanDefinition();
bd.setKlass(klass);
bd.setObject(object);
beanPool.put(klass, bd);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}.packageScanner(packageName);
}
/**
* //依赖注入重点方法:在注入成员时递归注入成员的成员
* @param bd
* @throws InJectFailException
*/
private void injectProperties(BeanDefinition bd) throws InJectFailException {
System.out.println("注入" + bd.getKlass().getName() + "的成员");
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;
}
Class<?> prototyklass = field.getType();
Object value = null;
BeanDefinition beanDefinition = getBeanDefinition(prototyklass);
//如果取出的类的定义是null,说明实要去找真正实现类
if (beanDefinition == null) {
//如果指定了其要取那个类就按照那个去取
if (field.isAnnotationPresent(Qualifier.class)) {
//如果找不到,去找它的父类是不是某个接口
BeanDefinition[] beans = searchBeanBySuperType(prototyklass);
if (beans.length == 1) {
value = beans[0].getObject();
}
//存在@Qualifier注解的成员才需要去找它的接口实现类,若没有直接抛出异常
//若存在的话一个实现类那么就将这个类注入,若存在多个实现类,根据@Qualifier注解中value的值来确定是哪个实现类
if (beans.length <= 0) {
throw new InJectFailException("类" + bd.getKlass() + "的成员" + field.getName() + "注入失败!");
} else {
Qualifier qualifier = field.getAnnotation(Qualifier.class);
String beanName = qualifier.ImplementationClass();
beanDefinition = getBeanDefinition(beanName);
if (beanDefinition == null) {
throw new InJectFailException("类" + bd.getKlass() + "的成员" + field.getName() + "注入失败!");
}
//继续调用实现类进行注入
value = getBean(beanDefinition.getKlass());
}
}
//如果不是接口类,则去递归getBean
} else {
value = getBean(field.getType());
}
Autowired autowired = field.getAnnotation(Autowired.class);
boolean isSinglton = autowired.isSinglton();
//如果是单例
value = dealSinglton(isSinglton, value, prototyklass, field);
//最后给成员赋值
try {
field.setAccessible(true);
field.set(object, value);
} catch (IllegalAccessException e) {
throw new InJectFailException("成员" + field.getName() + "注入失败");
}
}
}
/**
* 处理单例情况
* @param isSinglton
* @param value
* @param prototyklass
* @param field
* @return
* @throws InJectFailException
*/
private Object dealSinglton(boolean isSinglton, Object value, Class<?> prototyklass, Field field) throws InJectFailException {
if (!isSinglton) {
try {
value = beanPool.get(prototyklass).getPropertyObject();
if (value == null) {
throw new HasNoBeanException("类["
+ prototyklass.getName() + "]的成员[" + field.getName() + "]没有对应的Bean");
}
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
throw new InJectFailException("成员" + field.getName() + "注入失败");
}
}
return value;
}
//寻找实现它的父类或者继承类
private BeanDefinition[] searchBeanBySuperType(Class<?> klass) {
List<BeanDefinition> beanList = new ArrayList<>();
for (BeanDefinition bean : beanPool.values()) {
Class<?> beanClass = bean.getKlass();
if (klass.isAssignableFrom(beanClass)) {
beanList.add(bean);
}
}
BeanDefinition[] beans = new BeanDefinition[beanList.size()];
beanList.toArray(beans);
return beans;
}
/**
* 在这里巧妙的解决了循环依赖(在文章的后面细祥 )
* @param klass
* @param
* @return
* @throws InJectFailException
*/
public <T> T getBean(Class<?> klass) throws InJectFailException {
BeanDefinition bd = getBeanDefinition(klass);
if (bd == null) {
throw new HasNoBeanException("类["
+ klass.getName() + "]没有对应的Bean");
}
Object object = bd.getObject();
if (!bd.isInject()) {
//解决了循环依赖的关键
bd.setInject(true);
//注入成员变量
injectProperties(bd);
}
return (T) object;
}
public <T> T getBean(String className) {
try {
return getBean(alias.get(className));
} catch (InJectFailException e) {
return null;
}
}
BeanDefinition getBeanDefinition(String className) {
return beanPool.get(alias.get(className));
}
BeanDefinition getBeanDefinition(Class<?> className) {
return beanPool.get(className);
}
}
以上就是IOC/DI的思想模拟实现,其实本质上还是反射机制
接下来详解如何巧妙的解决循环依赖:
举个栗子:现在有A依赖B,B依赖C,C依赖A,那在我们依赖创建到C时便又去找A,A还是显示没有好,那么久形成循环依赖
而这里巧妙的解决方法就是在生成A时就将它设置为已经注入,如下图所示就成功解决了循环依赖:
其实还应该有一个注解是@bean注解,用来解决假如该类无法加注解怎么办,比如该类是一个jar包中的类,那么我们的解决方案就是用这个bean注解,这个解决方法可以看博主写的这一篇:Bean方法注入),
这里我们来做测试:
package test;
import annotation.Autowired;
import annotation.Component;
/**
* @author quan
* @create 2020-06-25 11:53
*/
@Component
public class ClassOne {
@Autowired
private ClassTwo classTwo;
}
package test;
import annotation.Autowired;
import annotation.Component;
/**
* @author quan
* @create 2020-06-25 11:53
*/
@Component
public class ClassTwo {
@Autowired
public ClassThree ClassThree;
}
package test;
import annotation.Autowired;
import annotation.Component;
import annotation.Qualifier;
/**
* @author quan
* @create 2020-06-25 12:45
*/
@Component
public class ClassThree {
@Autowired
private ClassOne classOne;
}
public static void main(String[] args) {
BeanFactory beanFactory = new BeanFactory();
beanFactory.scanBeanByPackage("test");
try {
ClassThree three = beanFactory.getBean(ClassThree.class);
System.out.println(three);
} catch (InJectFailException e) {
e.printStackTrace();
}
}
package test;
/**
* @author quan
* @create 2020-06-25 16:24
*/
public class A {
}
package test;
import annotation.Autowired;
import annotation.Component;
/**
* @author quan
* @create 2020-06-25 16:24
*/
@Component
public class A1 extends A {
@Autowired(isSinglton = false)
public ClassOne classOne;
}
package test;
import annotation.Component;
/**
* @author quan
* @create 2020-06-25 16:24
*/
@Component
public class A2 extends A {
}
package test;
import annotation.Autowired;
import annotation.Component;
/**
* @author quan
* @create 2020-06-25 11:53
*/
@Component
public class ClassOne {
@Autowired
private ClassTwo classTwo;
}
package test;
import annotation.Autowired;
import annotation.Component;
import annotation.Qualifier;
/**
* @author quan
* @create 2020-06-25 12:45
*/
@Component
public class ClassThree {
@Autowired
@Qualifier(ImplementationClass = "A1")
public A a;
}
public static void main(String[] args) {
BeanFactory beanFactory = new BeanFactory();
beanFactory.scanBeanByPackage("test");
try {
ClassThree three = beanFactory.getBean(ClassThree.class);
System.out.println("注入完成");
System.out.println("得到: "+three);
} catch (InJectFailException e) {
e.printStackTrace();
}
}
结果如下: