您当前的位置: 首页 >  spring

陈橙橙丶

暂无认证

  • 4浏览

    0关注

    107博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

深入剖析Spring(五):IOC核心思想(代码篇)

陈橙橙丶 发布时间:2020-03-31 10:36:05 ,浏览量:4

在上一篇文章中,我们粗略的对Spring源码IOC这块过了一遍,那么这篇文章来简单写一个IOC的过程。由于理论性的东西都在上一篇解释过了,这篇咱就直接在代码中理解。

一、准备工作 1.1本文所用到的依赖包:
		
            org.projectlombok
            lombok
            1.18.12
        
        
            org.springframework
            spring-webmvc
            4.3.9.RELEASE
        
        
            javax.servlet
            servlet-api
            2.5
        
1.2 web.xml文件


    MVC Web Application

    
        CcMvc
        
        com.ccc.spring2.webmvc.XHDispatcherServlet
        
            
            contextConfigLocation
            classpath:application.properties
        
        
        1
    
    
        
        CcMvc
        /*
    

1.3 建立项目结构

我们模仿spring的项目结构

1.3.1 创建BeanFactory接口

在包beans下创建:

/**
 * @author chenxh
 * @date 2020/3/23 20:28
 * @Description: 单例工厂顶层
 * @modify:
 * @modifyDate:
 * @Description:
 */
public interface XHBeanFactory {
    /**
     * 根据beanName从IOC容器中获取一个实例Bean
     * spring中使用单例有利于管理和维护
     *
     */
    Object getBean(String beanName) throws Exception;

    Object getBean(Class beanClass) throws Exception;

}
1.3.2 创建BeanDefinition

在之前说道过在Spring容器启动的过程中,会将Bean解析成BeanDefinition结构。因此我们也创建一个,模仿spring的包名创建一个config包:

@Data
public class XHBeanDefinition {

    private String beanClassName; //全包名
    private boolean isLazyInit = false; //是否懒加载
    private String factoryBeanName; //类名首字母小写
    private boolean isSingleton = true; //是否单例
}
1.3.3 BeanDefinitionReader

这个方法主要作用是解析配置文件并将其封装成BeanDefinition对象供IOC操作,此方法在上几篇文章MVC中写过,这里就不在解释了。

package com.ccc.spring2.beans.support;

import com.ccc.spring2.beans.config.XHBeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 加载配置文件的类
 */
public class XHBeanDefinitionReader {

    private Properties config = new Properties();
    //定义配置文件,暂时写死
    private final String SCAN_PACKAGE = "scanPackage";
    //存储所有的类名
    private List registyBeanClasses = new ArrayList();  //全包名

    public XHBeanDefinitionReader(String... locations) {
        //通过URL定位找到对应的文件,转为文件流读取
        try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:", ""))) {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //进行扫描
        doScanner(config.getProperty(SCAN_PACKAGE));
    }

    private void doScanner(String scanPackage) {
        //转换为文件路径,实际上就是把.替换为/就OK了
        URL url = this.getClass().getResource("/" + scanPackage.replaceAll("\\.","/"));
        File classPath = new File(url.getFile());
        for (File file : classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPackage + "." + file.getName());
            } else {
                if (!file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                registyBeanClasses.add(className);
            }
        }

    }

    public Properties getConfig() {
        return this.config;
    }

    //扫描配置信息并内部封装成XHBeanDefinition对象,便于IOC操作
    public List loadBeanDefinitions(String... locations) {
        List result = new ArrayList();
        try {
            System.out.println("registyBeanClasses:"+registyBeanClasses);
            for (String className : registyBeanClasses) {
                Class beanClass = Class.forName(className);
                //如果是一个接口,是不能实例化的
                //用它实现类来实例化
                if(beanClass.isInterface()) { continue; }

                //beanName有三种情况:
                //1、默认是类名首字母小写
                //2、自定义名字
                //3、接口注入
                result.add(doCreateBeanDefinition(toLowerFirstCase(beanClass.getSimpleName()),beanClass.getName()));
                result.add(doCreateBeanDefinition(beanClass.getName(),beanClass.getName()));
                Class [] interfaces = beanClass.getInterfaces();
                for (Class i : interfaces) {
                    //如果是多个实现类,只能覆盖
                    //为什么?因为Spring没那么智能,就是这么傻
                    //这个时候,可以自定义名字
                    result.add(doCreateBeanDefinition(i.getName(),beanClass.getName()));
                }

            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }

    //把配置信息解析成BeanDefinition
    //把每一个配信息解析成一个BeanDefinition
    private XHBeanDefinition doCreateBeanDefinition(String factoryBeanName,String beanClassName){
        XHBeanDefinition beanDefinition = new XHBeanDefinition();
        beanDefinition.setBeanClassName(beanClassName);
        beanDefinition.setFactoryBeanName(factoryBeanName);
        return beanDefinition;
    }

    /**
     * 首字母小写
     */
    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
        chars[0] += (1在判断是否@Service、@Controller这些类注解->在判断是否@Autowried等注解。

对于IOC 整理就以上这些就介绍这么多,如果发现有补充的地方,我会继续添加,同时希望各位看过的伙伴们如果发现了问题能够及时批评指正,在此感谢。下一篇我会记录DI的过程。

上一篇:深入剖析Spring(四):IOC核心思想(源码分析篇)

关注
打赏
1648473527
查看更多评论
0.0547s