为了方便理解项目中的实现,我们先对IOC与DI进行简单的介绍
控制反转
IoC(Inverse of Control:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。所谓IOC一句话搞定:对象由Spring来创建、管理、装配。而DI(依赖注入)是实现IOC的一种方式。所谓的控制反转就是获取依赖对象的方式反转了。
Spring IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。 IOC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。
控制翻转怎么理解:举个例子,"对象a 依赖了对象 b,当对象 a 需要使用 对象 b的时候必须自己去创建。但是当系统引入了 IOC 容器后, 对象a 和对象 b 之前就失去了直接的联系。这个时候,当对象 a 需要使用 对象 b的时候, 我们可以指定 IOC 容器去创建一个对象b注入到对象 a 中"。对象a获得依赖对象b的过程由主动行为变为了被动行为,控制权翻转,这就是控制反转名字的由来。
核心代码实现
在下面的代码中,createBeanDefinitionMap是为了创建Bean名与BeanDefinition相对应的映射关系,BeanDefinition将包含该Bean的相关信息,如bean的类、bean是单例还是原型、bean是否需要被代理。
BeanDefinition的存在将有助于我们实现bean的创建。
根据前文我们对于IOC的介绍,可以知道,IOC本质上是一个容器,项目在初始化后,这个容器将包含一些项目中需要的Bean,这些bean有的是单例,有的是原型。对于单例bean,我们需要时就直接从单例池中取出,对于原型bean,我们在需要使用时直接创建即可,这部分在下文代码的 getBean() 部分。在创建bean时,我们要对bean中被@Autowired的字段进行注入,这是依赖注入过程,这部分在下文代码的 doCreateBean() 部分。
public class BeanHelper {
private static String aspectPath="com.luban.demo.controller";
private static Map<String,BeanDefinition> beanDefinitionMap=new HashMap<String, BeanDefinition>();
//单例池
public static Map<String,Object> singletonObjects=new HashMap<String, Object>();
private static Map<Class<?>,Object> aopMap;
static {
// 创建BeanDefinitionMap
createBeanDefinitionMap();
//初始化
AopHelper aopHelper=new AopHelper();
aopMap=aopHelper.getProxyMap();
instanceSingletonBean();
}
public static void createBeanDefinitionMap(){
Set<Class<?>> classSet=new ClassHelper().getAllClass();
//将所有beanDefinition实例化并放入容器
for (Class<?> beanClass:classSet) {
if (beanClass.isAnnotationPresent(Component.class)) {
Component componentAnnotation = beanClass.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setAspect(beanClass.getName().startsWith(aspectPath));
//如果clazz是被Scope注解的类
if (beanClass.isAnnotationPresent(Scope.class)) {
//获取clazz上Scope的注解信息,获取bean的作用范围Scope
Scope scopeAnnotation = beanClass.getAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
} else {
//单例
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}else if (beanClass.isAnnotationPresent(Service.class)){
Service componentAnnotation = beanClass.getAnnotation(Service.class);
String beanName = componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setAspect(beanClass.getName().startsWith(aspectPath));
//如果clazz是被Scope注解的类
if (beanClass.isAnnotationPresent(Scope.class)) {
//获取clazz上Scope的注解信息,获取bean的作用范围Scope
Scope scopeAnnotation = beanClass.getAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
} else {
//单例
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
}
}
public static void instanceSingletonBean() {
for (String beanName:beanDefinitionMap.keySet()){
BeanDefinition beanDefinition= (BeanDefinition) beanDefinitionMap.get(beanName);
//如果是单例bean,需要存入单例池
if (beanDefinition.getScope().equals("singleton")){
//创建bean,对于被AOP的类,直接加强放入到singletonObjects的map中
if (!singletonObjects.containsKey(beanName)){
Object bean=doCreateBean(beanName,beanDefinition);
singletonObjects.put(beanName,bean);
}
}
}
}
private static Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
//实例化,利用java的反射机制完成
try {
//1.实例化
Class<?> beanClass=beanDefinition.getBeanClass();
Object instance;
//实例化bean
instance=beanClass.getDeclaredConstructor().newInstance();
//2.属性填充/依赖注入
//Field即字段即类中的成员变量
//getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
//getDeclaredFields()获得某个类的所有声明的字段,即包括public、private和proteced
Field[] fields=beanClass.getDeclaredFields();
for (Field field:fields){
//如果该字段采用Autowired注入
if (field.isAnnotationPresent(AutoWired.class)){
String fieldName=field.getName();
Object o=getBean(fieldName);
//开启field的set模式
field.setAccessible(true);
//将bean的field字段设置为o
field.set(instance,o);
}
}
//3.回调,设置beanName
if (instance instanceof BeanNameAWare){
((BeanNameAWare)instance).setBeanName(beanName);
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public static Object getBean(String beanName){
// beanName 单例的,原型的
BeanDefinition beanDefinition= beanDefinitionMap.get(beanName);
Object bean=null;
if (beanDefinition.getScope().equals("prototype")){
//如果是原型bean,创建一个新的
bean=doCreateBean(beanName,beanDefinition);
}else if (beanDefinition.getScope().equals("singleton")){
//否则,从单例池中加载
bean=singletonObjects.get(beanName);
if (bean==null){
Object bean1=doCreateBean(beanName,beanDefinition);
singletonObjects.put(beanName,bean1);
return bean1;
}
}
return bean;
}
public static void setBeanPraoxy(Class<?> targetClass, Object proxy) {
String name = null;
for (Map.Entry<String,BeanDefinition> entry:beanDefinitionMap.entrySet()){
BeanDefinition beanDefinition=entry.getValue();
if (beanDefinition.getBeanClass().equals(targetClass)){
name=entry.getKey();
break;
}
}
singletonObjects.put(name,proxy);
}
}