学习总结与分享-Spring IOC尝试自实现仿IOC容器

Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。也是几乎所有Java工作者必须要掌握的框架之一,其优秀的设计思想以及其代码实现上的艺术也是我们需要掌握的。要学习Spring,除了在我们的项目中使用之外,也需要对它的源码进行研读,但是Spring的实现涵盖的知识很多,在加上其中的类的数量也是非常的多,在我们阅读源码时可能会在几十个类之间穿插阅读,很有可能一不小心就导致思维混乱。有鉴于此,我这里先对Spring中的几个重要的模块进行一个手动的简易实现,一是熟悉这些模块的原理,同时也是仿造Spring中的结构来对后面阅读源码打下基础。
IOC(Inversion of Control)
Inversion of Control即控制反转,其意思是将我们之前由客户端代码来创建的对象交由IOC容器来进行控制,对象的创建,初始化以及后面的管理都由IOC完成。
IOC的好处
解耦:IOC的出现解决了类于类之间的耦合,我们在Web开发的Servlet时代,如果一个Servlet需要依赖另一个类的某些实现,那么我们需要在当前类对依赖的类进行创建和初始化,如果其他类也依赖了这个类,那也需要进行创建和初始化,而交给了IOC来管理的话,那么在需要的时候只需向IOC进行申请,而不需要重复的创建和初始化。当然,IOC也允许每次都重新创建一个新的对象。
方便与AOP进行配合:AOP也是一个使用十分频繁的功能,通过IOC可以十分方便的与AOP进行配合。
IOC中设计的设计模式
工厂模式。IOC容器来负责创建管理类实例对象,在需要时向IOC进行申请,从IOC中获取。所以IOC容器也称为bean工厂。
工厂模式是一种比较简单易懂的设计模式,这里就不在介绍了。
而要自己写出一个IOC容器是很难以实现的,所以这里就只是仿照IOC的源码,将主线流程梳理,模拟。
首先第一步就是要梳理好IOC源码中所涉及到几大接口、父类与他们各自的职责
IOC的入口就是context容器,不管是使用注解的方式还是xml的方式,他们的顶级父类就是AbstractApplicationContext,来完成初始化工厂与IOC容器所需要的bean对象,而在创建容器实现类的时候又进行了bean扫描,bean注册,bean的获取与创建几个步骤。
1、bean扫描
类:BeanDefinitionScanner
方法:scan();
2、bean注册
类: BeanDefinitionRegistry
方法:registerBeanDefinition();
3、容器
类:AbstractApplicationContext
方法:refresh(),finish(),close()
4、bean的获取和创建
类:BeanFactory
方法:getBean() ,createBean() ,registry();
AbstractApplicationContext与AnnotationConfigApplicationContext

//实现了BeanDefinitionRegistry接口,并重写其中的注册方法,在创建容器时在构造方法中调用
public class AbstractApplicationContext implements BeanDefinitionRegistry {

    public ConfigurableListableBeanFactory beanFactory;


    public AbstractApplicationContext(){
        //创建bean工厂
        beanFactory=new ConfigurableListableBeanFactory();

    }

    public void registryBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        beanFactory.registryBeanDefinition(beanName,beanDefinition);
    }

    public void refresh(){

        // 获取bean工厂
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 工厂信息初始化完成后,开始创建单例非懒加载的bean
        finishBeanFactoryInitialization(beanFactory);


    }

    //完成工厂初始化
    private void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        //设置数据格式转换器
        //添加环境变量解析器到容器中
        //初始所有需要进行代码植入的对象LoadTimeWeaverAware
        //设置临时类加载器
        //锁定所有bean的配置信息,此后不允许再进行改变

        // 实例化所有非懒加载的bean对象
        beanFactory.preInstantiateSingletons();

    }

    private ConfigurableListableBeanFactory obtainFreshBeanFactory() {
     return this.beanFactory;
    }


}
//实现了BeanFactory接口,实现了getBean方法,创建容器后获取bean对象使用
//继承AbstractApplicationContext,创建容器后刷新容器并创建需要注册的bean对象
public class AnnotationConfigApplicationContext extends AbstractApplicationContext implements BeanFactory {

    private BeanDefinitionScanner beanDefinitionScanner;


    AnnotationConfigApplicationContext() {
        //创建扫描器
        beanDefinitionScanner = new BeanDefinitionScanner(this);

    }


    public AnnotationConfigApplicationContext(String basePackge) {
        //先实例化beanFactory,创建一个beanScanner
        this();
        //扫描
        beanDefinitionScanner.scan(basePackge);
        //刷新容器
        refresh();


    }

    public Object getBean(String beanName) {
        return beanFactory.getBean(beanName);
    }
}

BeanDefinitionScanner扫描器
在创建容器时先创建扫描器,将扫描到的bean信息注册到工厂。

public class BeanDefinitionScanner {

    private BeanDefinitionRegistry registry;

    private Set<Class<?>> beanClass = new HashSet<Class<?>>();

    public BeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }


    public void scan(String basePackge) {
        doScan(basePackge);

    }

    private void doScan(String basePackge) {
        //扫描带有@Component注解的class
        Set<BeanDefinition> beanDefinitions = findComponent(basePackge);
        //解析懒加载、是否单例属性
        for (BeanDefinition beanDefinition : beanDefinitions) {
            beanDefinition.setLazy(false);
            beanDefinition.setSigle(true);
            //注册到容器
            registry.registryBeanDefinition(beanDefinition.getBeanName(), beanDefinition);

        }


    }

    private Set<BeanDefinition> findComponent(String basePackge) {
        Set<BeanDefinition> beanDefinitions = new HashSet<BeanDefinition>();
        //加载所有class
        loadClass(basePackge);

        //解析带有@Component注解的class
        for (Class cls : beanClass) {
            if (cls.isAnnotationPresent(ArdComponent.class) || cls.isAnnotationPresent(ArdService.class)) {
                BeanDefinition beanDefinition = new BeanDefinition();
                beanDefinition.setBeanClass(cls);
                beanDefinition.setBeanName(BeanNameUtil.getBeanName(cls.getSimpleName()));
                beanDefinitions.add(beanDefinition);
            }
        }

        return beanDefinitions;
    }


    private void loadClass(String scanPath) {
        try {
            String filePath = scanPath.replace(".", "/");
            URL url = this.getClass().getClassLoader().getResource(filePath);
            File file = new File(url.toURI());
            doLoadClass(file, filePath);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

    }

    private void doLoadClass(File file, String scanPath) {
        //文件夹
        if (file.isDirectory()) {
            File[] fileList = file.listFiles();
            for (File f : fileList) {
                doLoadClass(f, scanPath + "/" + f.getName());
            }
        }

        //文件
        if (file.getName().indexOf(".class") > 0) {
            try {
                //文件夹格式转为包格式
                String packgePath = scanPath.replace("/", ".");

                Class cls = Class.forName(packgePath.replace(".class", ""));
                beanClass.add(cls);
            } catch (ClassNotFoundException e) {
                System.out.println("解析class错误。。。。");
                e.printStackTrace();
            }

        }
    }
}

BeanDefinitionRegistry注册
Bean信息的注册接口,由bean工厂实现,将扫描到bean信息存入容器中生成bean对象时使用。

public interface BeanDefinitionRegistry {

    public void registryBeanDefinition(String beanName, BeanDefinition beanDefinition);
}

BeanFactory与ConfigurableListableBeanFactory工厂接口与工厂实现类
为容器提供getBean()方法,实现BeanDefinitionRegistry注册接口,实现bean的注册与创建bean放入核心容器中。

//提供获取bean的方法。
public interface BeanFactory {

    public Object getBean(String beanName);

}

//实现了注册接口,为核心容器提供了getBean实现接口与注册bean信息和生成bean的方法。
//注:在生成bean时使用三级缓存的方式解决了循环依赖的问题。
public class ConfigurableListableBeanFactory implements BeanDefinitionRegistry,BeanFactory{

    private ConcurrentHashMap<String,BeanDefinition> BeanDefinitionMap=new ConcurrentHashMap();

    //缓存所有已经创建完成的单例bean
    private  ConcurrentHashMap<String,Object> singletonObjects=new ConcurrentHashMap();
    //缓存正在创建的bean
    private  ConcurrentHashMap<String,Object> singletonsCurrentlyInCreation=new ConcurrentHashMap();
    //缓存所正准备创建的bean
    private  ConcurrentHashMap<String,Object> singletonFactories=new ConcurrentHashMap();

    //保存所有BeanPostProcessor
    private Set<BeanPostProcessor> beanPostProcessorSet=new HashSet<BeanPostProcessor>();

    public void registryBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        BeanDefinitionMap.put(beanName,beanDefinition);
    }

    /**
     * 实例化所有单例非懒加载的bean
     */
    public void preInstantiateSingletons() {
        //获取所有bean的定义信息

        // 遍历初始化所有 非来加载并且为单例的bean信息

        //调用getBean()进行bean的实例化

        for(BeanDefinition beanDefinition:BeanDefinitionMap.values()){
            //如果非懒加载并且为单例,创建bean
            if(!beanDefinition.isLazy()&&beanDefinition.isSigle()){
                getBean(beanDefinition.getBeanName());
            }
        }

    }


    public Object getBean(String beanName) {
       Object object= doGetBean( beanName);
        if(object instanceof BeanPostProcessor){
         beanPostProcessorSet.add((BeanPostProcessor)object);
        }
        return object;
    }


    /**
     * 获取bean
     * @param beanName
     * @return
     */
    private Object doGetBean(String beanName) {
        //从缓存获取
        if(singletonObjects.containsKey(beanName)){
            return singletonObjects.get(beanName);
        }
        //缓存没有就创建
        return createBean(beanName);
    }

    private Object createBean(String beanName) {

        //确保已经解析了bean的定义信息,没有的话则重新创建bean的定义信息
        //准备需要overrides覆盖的方法
        // ==BeanPostProcessorsBeforeInstantiation 的扩展实现,返回代理对象

        //====正式开始创建bean
        return doCreateBean(beanName);
        }

    private Object doCreateBean(String beanName) {

        //先验证循环依赖
        if(singletonsCurrentlyInCreation.containsKey(beanName)||singletonFactories.containsKey(beanName)){
            System.out.println("可能存在循环依赖"+beanName);
            throw  new RuntimeException("可能存在循环依赖");
        }
        //标记正准备创建,放到三级缓存
        singletonFactories.put(beanName,"");
        //创建对象实例
        BeanWrapper beanWrapper=createInstance(beanName);
        //标记对象正在创建中 放到二级缓存
        singletonsCurrentlyInCreation.put(beanName,beanWrapper.getBeanInstance());
        singletonFactories.remove(beanName);

        //属性注入
        populateBean(beanWrapper);

        Object expactIntance= initializeBean(beanName,beanWrapper);

        //放到一级缓存里
        singletonObjects.put(beanName,expactIntance);
        singletonsCurrentlyInCreation.remove(beanName);

        return expactIntance;
    }


    private Object initializeBean(String beanName,BeanWrapper beanWrapper) {
        Object object=beanWrapper.getBeanInstance();
        //获取所有实现了beanPostProcessor的接口
        for(BeanPostProcessor beanPostProcessor:this.beanPostProcessorSet){
            object=beanPostProcessor.postProcessBeforeInitialization(beanWrapper.getBeanInstance(),beanName);
        }
        //先执行beanPostProcessor  postProcessBeforeInitialization
        //在执行init
        System.out.println("调用 init方法.....");

        for(BeanPostProcessor beanPostProcessor:this.beanPostProcessorSet){
            object=beanPostProcessor.postProcessAfterInitialization(beanWrapper.getBeanInstance(),beanName);
        }
        return object;
    }

    /**
     * 依赖注入
     */
    private void populateBean(BeanWrapper beanWrapper) {
        //1属性赋值

        //2依赖注入

        //2.1获取对象属性中带有@ArdAutowired的属性
        Field[] fields=beanWrapper.getBeanInstance().getClass().getDeclaredFields();
        for(Field field:fields){
            if(field.isAnnotationPresent(ArdAutowired.class)){
                //获取属性bean的名称
                String beanName= BeanNameUtil.getBeanName(field.getType().getSimpleName());
                Object populateBeanInstance=null;

                //看一级和二级缓存有没有
                if(singletonObjects.containsKey(beanName)){
                    populateBeanInstance=singletonObjects.get(beanName);
                }

                if(populateBeanInstance==null&&singletonsCurrentlyInCreation.containsKey(beanName)){
                    populateBeanInstance=singletonsCurrentlyInCreation.get(beanName);
                }

                if(populateBeanInstance==null){
                    populateBeanInstance=getBean(beanName);
                }
                //属性赋值
                beanWrapper.setBeanProperty(beanName,populateBeanInstance);
            }


        }




        //没有就调用getBean();

        //给属性赋值


    }


    /**
     * 创建bean
     * @param beanName
     * @return
     */
    private BeanWrapper createInstance(String beanName) {
        try {
            BeanDefinition beanDefinition=BeanDefinitionMap.get(beanName);
            Object object= beanDefinition.getBeanClass().newInstance();
            BeanWrapper beanWrapper=new BeanWrapper();
            beanWrapper.setBeanInstance(object);
            beanWrapper.setBeanClass(beanDefinition.getBeanClass());
            return  beanWrapper;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return null;
    }
}

//解析bean时的工具类,封装通用方法
public class BeanNameUtil {

    //解析首字母小写的bean
    public static  String getBeanName(String beanName){
        return beanName.substring(0,1).toLowerCase()+beanName.substring(1,beanName.length());

    }
}

BeanDefinition与BeanWrapper实体类
封装bean注册时的信息实体类与创建bean时的实例。

//封装注册bean时所需的参数,初始化工厂时使用。
@Data
public class BeanDefinition {
    //bean名称
    private String beanName;
    //bean的class
    private Class<?> beanClass;
    //是否单例
    private boolean isSigle;
    //是否懒加载
    private boolean isLazy;

}

//封装已实例化的bean与字节对象。提供设置对象属性的方法,使用反射的方式。
@Data
public class BeanWrapper {

    private Object beanInstance;

    private   Class<?>  beanClass;

    /**
     * 设置对象属性
     * @param propertyName
     * @param object
     */
    public void setBeanProperty(String propertyName,Object object){
        try {
        //获得属性
        Field[] beanFile=beanClass.getDeclaredFields();
        //匹配属性名,并设值
        for(Field file:beanFile){
            file.setAccessible(true);
            if(  file.getName().equals(propertyName)){
                file.set(beanInstance,object);
            }
        }
        } catch (IllegalAccessException e) {
            System.out.println("设置属性名失败....");
            e.printStackTrace();
        }

    }

}

@XXXAutowired
@XXXComponent
@XXXService

自定义依赖注入注解与标记需要放入容器创建bean的注解。
注:@XXXService将继承@XXXComponent注解,在扫描器进行扫描时只会扫描标记有XXXComponent注解的类。

UserDao
UserService 实体类

需要创建bean的实体类,service层依赖注入dao层对象。

TestAnnotationConfigApplicationContext
创建核心容器,测试仿IOC代码。

public class TestAnnotationConfigApplicationContext{

    public static void main(String[] args) {
        AnnotationConfigApplicationContext configApplicationContext=new AnnotationConfigApplicationContext("com.test.scanPackage");
        UserService userService=(UserService) configApplicationContext.getBean("userService");
        userService.getUserInfo("testSuccess");
    }
}

扩展:BeanPostProcessor
创建bean时的后置处理器接口,实现该接口可以在工厂初始化bean后更改bean的属性等处理。

//提供前置处理与后置处理方法。
public interface BeanPostProcessor {
	//前置处理
	public Object postProcessBeforeInitialization(Object bean, String beanName);
	//后置处理
	public Object postProcessAfterInitialization(Object bean, String beanName);

}

//每次初始化bean时都会将所有的Proccessor处理器全部执行一次。
@XXXComponent
public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println(beanName);
        System.out.println("MyBeanPostProcessor   before");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println(beanName);
        System.out.println("MyBeanPostProcessor   after");
        return bean;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值