Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。也是几乎全部Java工做者必需要掌握的框架之一,其优秀的设计思想以及其代码实现上的艺术也是咱们须要掌握的。要学习Spring,除了在咱们的项目中使用以外,也须要对它的源码进行研读,可是Spring的实现涵盖的知识不少,在加上其中的类的数量也是很是的多,在咱们阅读源码时可能会在几十个类之间穿插阅读,颇有可能一不当心就致使思惟混乱。有鉴于此,我这里先对Spring中的几个重要的模块进行一个手动的简易实现,一是熟悉这些模块的原理,同时也是仿造Spring中的结构来对后面阅读源码打下基础。html
Inversion of Control即控制反转,其意思是将咱们以前由客户端代码来建立的对象交由IOC容器来进行控制,对象的建立,初始化以及后面的管理都由IOC完成。设计模式
工厂模式。IOC容器来负责建立管理类实例对象,在须要时向IOC进行申请,从IOC中获取。因此IOC容器也称为bean工厂。bash
工厂模式是一种比较简单易懂的设计模式,这里就不在介绍了,若是有须要的能够看看这个:工厂模式。并发
IOC的主要的功能即是对Bean进行管理,包括建立、初始化、管理以及销魂的工做。首先咱们面对的问题就是咱们怎么让IOC可以建立一个Bean?为了建立Bean咱们须要提供一些什么?框架
在不手动经过new关键字建立的状况下建立类实例的对象方法有两种:ide
clazz.getClass().newInstance();
。public class PersonFactory{
public Person getPerson(){
return new Person();
}
}
复制代码
经过分析上面的两种方法能够轻松得出答案。post
对于反射的方式咱们仅需提供实例的Class对象。学习
对于工厂方法咱们须要提供的就是建立该类的工厂名(factoryName)和方法名(methodName);测试
IOC容器是对bean的整个生命周期进行管理,除了建立以外还须要对bean进行初始化,以及不须要时对bean进行销毁的工做(如释放资源等)。因此咱们还须要提供初始化和销毁等操做。ui
到这里建立bean须要的基本分析完了,看类图:
Bean的定义解决了,可是这个bean定义以及建立好的Bean实例放在哪里呢,咱们须要一个统一的地方来存放这些东西以方便咱们要用的时候方便取。
咱们定义一个Bean工厂来存放bean,在须要的时候懂bean工厂中取便可,bean工厂对外提供的也仅仅是一个获取bean的方法便可,因为bean的类型不定,因此返回值定位Object。
到了如今咱们有了建立bean的Bean定义,有了存放和管理bean的Bean工厂,如今须要考虑的事怎么来联系这两个类,咱们还须要另一个接口,接口的功能是让咱们能注册和获取bean定义,这里咱们经过beanName来区分不一样的bean。
到这里咱们实现一个简易的IOC容器的须要的东西基本准备完成了,看下基本类图:
基本代码实现:
DefaultBeanDefinition:
public class DefaultBeanDefinition implements BeanDefinition{
private Class<?> clazz;
private String beanFactoryName;
private String createBeanMethodName;
private String staticCreateBeanMethodName;
private String beanInitMethodName;
private String beanDestoryMethodName;
private boolean isSingleton;
// setter
public void setSingleton(boolean singleton) {
isSingleton = singleton;
}
@Override
public Class<?> getBeanClass() {
return this.clazz;
}
@Override
public String getBeanFactory() {
return this.beanFactoryName;
}
@Override
public String getCreateBeanMethod() {
return this.createBeanMethodName;
}
@Override
public String getStaticCreateBeanMethod() {
return this.staticCreateBeanMethodName;
}
@Override
public String getBeanInitMethodName() {
return this.beanInitMethodName;
}
@Override
public String getBeanDestoryMethodName() {
return this.beanDestoryMethodName;
}
@Override
public String getScope() {
return this.isSingleton?BeanDefinition.SINGLETION :BeanDefinition.PROTOTYPE;
}
@Override
public boolean isSingleton() {
return this.isSingleton;
}
@Override
public boolean isPrototype() {
return !this.isSingleton;
}
}
复制代码
DefaultBeanFactory:
public class DefaultBeanFactory implements BeanFactory, BeanDefinitionRegistry, Closeable {
private Log log = LogFactory.getLog(this.getClass());
//ConcurrentHashMap应对并发环境
private Map<String, BeanDefinition> bdMap = new ConcurrentHashMap<>();
private Map<String, Object> beanMap = new ConcurrentHashMap<>();
@Override
public void register(BeanDefinition bd, String beanName) {
Assert.assertNotNull("beanName不能为空 beanName", beanName);
Assert.assertNotNull("BeanDefinition不能为空", bd);
if(bdMap.containsKey(beanName)){
log.info("[" + beanName + "]已经存在");
}
if(!bd.validate()){
log.info("BeanDefinition不合法");
}
if(!bdMap.containsKey(beanName)){
bdMap.put(beanName, bd);
}
}
@Override
public boolean containsBeanDefinition(String beanName) {
return bdMap.containsKey(beanName);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) {
if(!bdMap.containsKey(beanName)){
log.info("[" + beanName + "]不存在");
}
return bdMap.get(beanName);
}
public Object doGetBean(String beanName) throws InstantiationException, IllegalAccessException {
if(!beanMap.containsKey(beanName)){
log.info("[" + beanName + "]不存在");
}
Object instance = beanMap.get(beanName);
if(instance != null){
return instance;
}
//不存在则进行建立
if(!this.bdMap.containsKey(beanName)){
log.info("不存在名为:[" + beanName + "]的bean定义");
}
BeanDefinition bd = this.bdMap.get(beanName);
Class<?> beanClass = bd.getBeanClass();
if(beanClass != null){
instance = createBeanByConstruct(beanClass);
if(instance == null){
instance = createBeanByStaticFactoryMethod(bd);
}
}else if(instance == null && StringUtils.isNotBlank(bd.getStaticCreateBeanMethod())){
instance = createBeanByFactoryMethod(bd);
}
this.doInit(bd, instance);
if(instance != null && bd.isSingleton()){
beanMap.put(beanName, instance);
}
return instance;
}
private void doInit(BeanDefinition bd, Object instance) {
Class<?> beanClass = instance.getClass();
if(StringUtils.isNotBlank(bd.getBeanInitMethodName())){
try {
Method method = beanClass.getMethod(bd.getBeanInitMethodName(), null);
method.invoke(instance, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 构造方法建立实例
* @param beanClass
* @return
*/
private Object createBeanByConstruct(Class<?> beanClass) {
Object instance = null;
try {
instance = beanClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
/**
* 普通工厂方法建立实例
* @param bd
* @return
*/
private Object createBeanByFactoryMethod(BeanDefinition bd) {
Object instance = null;
try {
//获取工厂类
Object factory = doGetBean(bd.getBeanFactory());
//获取建立实例的方法
Method method = factory.getClass().getMethod(bd.getCreateBeanMethod());
//执行方法
instance = method.invoke(factory, null);
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
/**
* 静态方法建立实例
* @param bd
* @return
*/
private Object createBeanByStaticFactoryMethod(BeanDefinition bd) {
Object instance = null;
try {
Class<?> beanClass = bd.getBeanClass();
//获取建立实例的方法
Method method = beanClass.getMethod(bd.getStaticCreateBeanMethod());
instance = method.invoke(beanClass, null);
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
@Override
public Object getBean(String beanName) {
if(!beanMap.containsKey(beanName)){
log.info("[" + beanName + "]不存在");
}
return beanMap.get(beanName);
}
@Override
public void close() throws IOException {
Set<Map.Entry<String, BeanDefinition>> entries = bdMap.entrySet();
for(Map.Entry<String, BeanDefinition> entry: entries){
BeanDefinition value = entry.getValue();
String destoryMethodName = value.getBeanDestoryMethodName();
try {
Method method = value.getBeanClass().getMethod(destoryMethodName, null);
method.invoke(value.getBeanClass(), null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
复制代码
简单测试一下: 实例bean:
public class User {
private String name;
private int age;
//getter setter
public void init(){
System.out.println("init...");
}
public void destory(){
System.out.println("destory...");
}
}
复制代码
工厂类:
public class TestFactory {
public Object createMethod(){
return new User();
}
public static Object staticCreateMethod(){
return new User();
}
}
复制代码
测试类:
public class MySpringTest {
static DefaultBeanFactory factory = new DefaultBeanFactory();
@Test
public void test() throws IllegalAccessException, InstantiationException {
DefaultBeanDefinition bd = new DefaultBeanDefinition();
bd.setClazz(User.class);
bd.setSingleton(true);
bd.setBeanFactoryName("TestFactory");
bd.setCreateBeanMethodName("createMethod");
bd.setStaticCreateBeanMethodName("staticCreateMethod");
bd.setBeanInitMethodName("init");
factory.register(bd, "user");
System.out.println(factory.doGetBean("user"));
}
}
复制代码
一个简易的容器就这样实现了,固然咱们这里只是具有了基本的功能,实际上还差的远,好比带参数的bean的实例化等功能。可是IOC的基本原理已经表达出来了,后面咱们只需在这个基础上添加新的功能便可。