手写MVC初体验之功能类(三)

手写MVC初体验之功能类(三)

1. 项目结构

结构图

流程图

在(二)中解释了bean的config包下的类的作用。这篇文章记录一下自己在support下的类。

  • reader包:对应上图的BeanDefinitionReader类,用来扫描指定包下的类,将其封装为类路径的String集合。
  • loader包:对应上图的ResourceLoader,属于BeanDefinitionReader的功能类,为其解析application.properties中的配置。
  • registry包:对应上图的BeanDefinitionRegistry,将BeanDefinitionReader扫描到的类路径封装成BeanDefinition。
  • wrapper包:对应上图的BeanWrapperProcess,将BeanDefinitionRegistry封装的BeanDefinition包装成BeanWrapper。
  • autowire包:对应上图的BeanPostProcessor,将BeanWrapper中的实例对象进行依赖注入。
  • factory包:对应上图的FactoryBean,为autowire包的操作提供bean的注入。

2. ApplicationContext

package org.framework.spring.v1.context.core.impl;

import org.framework.spring.v1.context.bean.support.autowire.BeanPostProcessor;
import org.framework.spring.v1.context.bean.support.autowire.factory.BeanPostProcessorFactory;
import org.framework.spring.v1.context.bean.support.reader.BeanDefinitionReader;
import org.framework.spring.v1.context.bean.support.reader.factory.BeanDefinitionReaderFactory;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;
import org.framework.spring.v1.context.bean.support.wrapper.factory.BeanWrapperProcessFactory;
import org.framework.spring.v1.context.core.ApplicationContext;

import java.util.Map;


/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/6/18 21:43
 */

public class AnnotationApplicationContext implements ApplicationContext {

    private BeanDefinitionReader reader ;

    private BeanDefinitionRegistry registry ;

    private BeanWrapperProcess process ;

    private BeanPostProcessor beanFactory ;

    /**
     * 传入的是application.properties
     * @param contextConfiguration
     */
    public AnnotationApplicationContext(String contextConfiguration) {

        //通过reader加载配置文件
        this.reader = BeanDefinitionReaderFactory.getAnnotation(contextConfiguration) ;
        //注册 beanDefinitionMap
        //一级缓存——beanName->BeanDefinition 交由reader下面的registry处理
        this.registry = this.reader.getRegistry() ;
        //二级缓存——BeanDefinition->BeanWrapper 交由process处理
        this.process = BeanWrapperProcessFactory.getBeanWrapperProcess(this.registry) ;
        //三级缓存——BeanWrapper->Bean
        this.beanFactory = BeanPostProcessorFactory.getAutowireCapable(this.process) ;
    }

    @Override
    public Map<String, Object> getIoc() {
        return this.beanFactory.getIoc() ;
    }

    @Override
    public void registerBean(String className) {
        //首先是registerClassName列表中

        //registry的BeanDefinition

        //process的BeanDefinition

        //beanFactory的Object

    }

    @Override
    public void removeBean(String beanName) {
        //首先是registerClassName列表中

        //registry的BeanDefinition

        //process的BeanDefinition

        //beanFactory的Object
    }

    @Override
    public int getIocCount() {
        return this.beanFactory.getBeanCount() ;
    }

    @Override
    public boolean isBeanExist(Object bean) {
        return this.beanFactory.isBeanExist(bean) ;
    }

    @Override
    public boolean isBeanNameExist(String beanName) {
        return this.beanFactory.isBeanNameExist(beanName) ;
    }

}

3. Reader

package org.framework.spring.v1.context.bean.support.reader;

import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/6/22 23:49
 */
public interface BeanDefinitionReader {

    void doScanner(String scanPackage) ;

    BeanDefinitionRegistry getRegistry();

    BeanDefinitionRegistry getBeanFactory();
}

package org.framework.spring.v1.context.bean.support.reader.abs;

import org.framework.spring.v1.context.bean.support.loader.ResourceLoader;
import org.framework.spring.v1.context.bean.support.reader.BeanDefinitionReader;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;

import java.util.ArrayList;
import java.util.List;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/5 20:06
 */

public abstract class AbstractAnnotationBeanDefinitionReader implements BeanDefinitionReader {

    protected ResourceLoader loader ;

    protected BeanDefinitionRegistry registry ;

    protected List<String> registerBeanClasses ;

    public AbstractAnnotationBeanDefinitionReader(){
        this.registerBeanClasses = new ArrayList<String>() ;
    }

    /**
     * 加载BeanDefinition
     */
    protected abstract void loadBeanDefinitions() ;
}

package org.framework.spring.v1.context.bean.support.reader.impl;

import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.config.definition.impl.DefaultRootBeanDefinition;
import org.framework.spring.v1.context.bean.support.loader.impl.PropertiesResourceLoader;
import org.framework.spring.v1.context.bean.support.reader.abs.AbstractAnnotationBeanDefinitionReader;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.registry.factory.BeanDefinitionRegistryFactory;
import org.framework.spring.v1.tools.StringUtil;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/6/18 22:57
 */

public class DefaultAnnotationBeanDefinitionReader extends AbstractAnnotationBeanDefinitionReader {


    public DefaultAnnotationBeanDefinitionReader(String config) {
        super();
        this.loader = new PropertiesResourceLoader(config) ;
        doScanner(this.loader.getProperty("spring.base.package")) ;
        this.registry = BeanDefinitionRegistryFactory.getAnnotation() ;
        loadBeanDefinitions();
    }

    /**
     * 交由registry处理
     * 通过扫描到的类,将类封装成BeanDefinition类型
     * @return
     */
    protected void loadBeanDefinitions(){
        List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>() ;
        //加载Bean,并且封装成BeanDefinition
        try{
            for (String registerBeanClass : registerBeanClasses) {
                Class<?> beanClass = Class.forName(registerBeanClass) ;
                //接口不做处理
                if (beanClass.isInterface()){
                    continue ;
                }
                BeanDefinition beanDefinition =
                        doCreateBeanDefinition(StringUtil.toLowerFirstAlp(beanClass.getSimpleName()) , beanClass.getName()) ;
                this.registry.registerBeanDefinition(beanDefinition.getFactoryBeanName() , beanDefinition) ;
                Class<?>[] interfaces = beanClass.getInterfaces() ;
                for (Class<?> anInterface : interfaces) {
                    //接口名首字母小写
                    beanDefinition = doCreateBeanDefinition(StringUtil.toLowerFirstAlp(anInterface.getName()) , beanClass.getName()) ;
                    //registry注册
                    this.registry.registerBeanDefinition(beanDefinition.getFactoryBeanName() , beanDefinition) ;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private BeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName) {
        BeanDefinition beanDefinition = new DefaultRootBeanDefinition(factoryBeanName , beanClassName) ;
        return beanDefinition ;
    }

    /**
     * application.properties下的scanPackage属性
     * @param scanPackage
     */
    @Override
    public void doScanner(String scanPackage) {
        if (StringUtil.isNull(scanPackage) || StringUtil.isPackageRegular(scanPackage)){
            throw new IllegalArgumentException("scanPackage of application.properties is error") ;
        }

        URL url = this.getClass().getClassLoader().getResource("/"+scanPackage.replaceAll("\\.","/"));
        //获取文件夹
        File classPath = new File(url.getFile()) ;

        for (File file : classPath.listFiles()) {
            if (file.isDirectory()) {
                //采用递归的方式
                doScanner(scanPackage + "." + file.getName());
                continue ;
            }
            if (!file.getName().endsWith(".class")) {
                continue;
            }
            registerBeanClasses.add(scanPackage + "." + file.getName().replace(".class","")) ;
        }
    }

    @Override
    public BeanDefinitionRegistry getRegistry() {
        return this.registry ;
    }

    @Override
    public BeanDefinitionRegistry getBeanFactory() {
        return this.registry ;
    }
}

4. Loader

package org.framework.spring.v1.context.bean.support.loader;

import org.framework.spring.v1.context.bean.config.resource.Resource;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/5 17:35
 */
public interface ResourceLoader {

    Resource getResource(String resource) ;

    String getProperty(String key) ;

}

package org.framework.spring.v1.context.bean.support.loader.impl;

import org.framework.spring.v1.context.bean.config.resource.Resource;
import org.framework.spring.v1.context.bean.config.resource.impl.DefaultResource;
import org.framework.spring.v1.context.bean.support.loader.ResourceLoader;
import org.framework.spring.v1.tools.StringUtil;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/9 10:28
 */

public class PropertiesResourceLoader implements ResourceLoader {

    private Resource resource ;

    public PropertiesResourceLoader(String config){
        //resource生成properties
        this.resource = new DefaultResource(config) ;
    }

    @Override
    public Resource getResource(String resource) {
        return this.resource ;
    }

    @Override
    public String getProperty(String key) {
        if (StringUtil.isNull(key)){
            return null ;
        }
        return this.resource.getProperty(key) ;
    }
}

5. Registry

package org.framework.spring.v1.context.bean.support.registry;

import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/6/22 23:22
 */

public interface BeanDefinitionRegistry {

    void registerBeanDefinition(String beanName , BeanDefinition beanDefinition) throws Exception;

    boolean removeBeanDefinition(String beanName) ;

    BeanDefinition getBeanDefinition(String beanName) ;

    boolean containsBeanDefinition(String beanName) ;

    String[] getBeanDefinitionNames() ;

    int getBeanDefinitionCount() ;

    boolean isBeanNameInUse(String beanName) ;
}

package org.framework.spring.v1.context.bean.support.registry.abs;

import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;

import java.util.Map;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/8 10:02
 */

public abstract class AbstractAnnotationBeanDefinitionRegistry implements BeanDefinitionRegistry {

    protected Map<String,BeanDefinition> beanDefinitionMap ;

}

package org.framework.spring.v1.context.bean.support.registry.impl;

import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.support.registry.abs.AbstractAnnotationBeanDefinitionRegistry;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/6/22 23:50
 */

public class AnnotationBeanDefinitionRegistry extends AbstractAnnotationBeanDefinitionRegistry {



    public AnnotationBeanDefinitionRegistry() {
        this(new ConcurrentHashMap<String, BeanDefinition>()) ;
    }

    public AnnotationBeanDefinitionRegistry(Map<String,BeanDefinition> beanDefinitionMap){
        this.beanDefinitionMap = beanDefinitionMap ;
    }


    public Map<String,BeanDefinition> getBeanDefinitionMap(){
        return this.beanDefinitionMap ;
    }

	//注册BeanDefinition
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception {
        if(this.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())){
            throw new Exception("the bean is exist ! { " + beanDefinition.getFactoryBeanName()+" }") ;
        }
        this.beanDefinitionMap.put(beanName , beanDefinition) ;
    }

    @Override
    public boolean removeBeanDefinition(String beanName) {
        this.beanDefinitionMap.remove(beanName) ;
        return false;
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return this.beanDefinitionMap.get(beanName);
    }

    @Override
    public boolean containsBeanDefinition(String beanName) {
        return this.beanDefinitionMap.containsKey(beanName) ;
    }

    @Override
    public String[] getBeanDefinitionNames() {
        Set<String> beanNameSet = this.beanDefinitionMap.keySet() ;
        String[] beanNames = beanNameSet.toArray(new String[beanNameSet.size()]) ;
        return beanNames ;
    }

    @Override
    public int getBeanDefinitionCount() {
        return this.beanDefinitionMap.size() ;
    }

    @Override
    public boolean isBeanNameInUse(String beanName) {
        return this.containsBeanDefinition(beanName) ;
    }
}

6. Wrapper

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FXrADqRj-1594568026709)(C:\Users\keydous\AppData\Roaming\Typora\typora-user-images\image-20200712232714343.png)]

package org.framework.spring.v1.context.bean.support.wrapper;

import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/5 23:16
 */
public interface BeanWrapperProcess {

    void registerBeanWrapper(BeanDefinition beanDefinition) ;

    boolean removeBeanWrapper(String beanName) ;

    BeanWrapper getBeanWrapper(String beanName) ;

    boolean containsBeanWrapper(String beanName) ;

    int getBeanWrapperCount() ;

    boolean isBeanWrapperExist(String beanName) ;

    String[] getBeanNames() ;
}

package org.framework.spring.v1.context.bean.support.wrapper.abs;

import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;

import java.util.Map;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/6 12:21
 */

public abstract class AbstractBeanWrapperProcess implements BeanWrapperProcess {

    protected Map<String , BeanWrapper> factoryBeanInstanceCache ;

    protected BeanDefinitionRegistry registry ;

    public AbstractBeanWrapperProcess(Map<String, BeanWrapper> factoryBeanInstanceCache , BeanDefinitionRegistry registry) {
        this.factoryBeanInstanceCache = factoryBeanInstanceCache;
        this.registry = registry ;
        init() ;
    }

    protected abstract void init() ;
}

package org.framework.spring.v1.context.bean.support.wrapper.impl;


import org.framework.spring.v1.context.annotation.Component;
import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;
import org.framework.spring.v1.context.bean.config.wrapper.impl.DefaultBeanWrapper;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.wrapper.abs.AbstractBeanWrapperProcess;
import org.framework.spring.v1.tools.StringUtil;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/5 23:14
 */

public class BeanWrapperProcessImpl extends AbstractBeanWrapperProcess {


    public BeanWrapperProcessImpl(Map<String, BeanWrapper> factoryBeanInstanceCache , BeanDefinitionRegistry registry) {
        super(factoryBeanInstanceCache ,registry);
    }

    @Override
    protected void init() {
        String[] beanNames = this.registry.getBeanDefinitionNames() ;
        for (String beanName : beanNames) {
            registerBeanWrapper(this.registry.getBeanDefinition(beanName));
        }
    }

    public BeanWrapperProcessImpl(BeanDefinitionRegistry registry){
        this(new ConcurrentHashMap<String, BeanWrapper>() , registry) ;
    }

    @Override
    public void registerBeanWrapper(BeanDefinition beanDefinition) {
        String beanName = beanDefinition.getFactoryBeanName() ;
        BeanWrapper beanWrapper = doCreateWrapper(beanDefinition) ;
        if (StringUtil.isNull(beanName) || beanWrapper == null){
            return ;
        }
        this.factoryBeanInstanceCache.put(beanName,beanWrapper) ;
    }

    private BeanWrapper doCreateWrapper(BeanDefinition beanDefinition) {
        String className = beanDefinition.getBeanClassName() ;
        try {
            Class<?> clazz = Class.forName(className) ;
            /**
             * 并不是所有的类都初始化,只有是组件的才初始化
             */
            if (!clazz.isAnnotationPresent(Component.class)){
                if (!clazz.isInterface()){
                    return null ;
                }
            }
            Object bean = clazz.newInstance() ;
            BeanWrapper beanWrapper = new DefaultBeanWrapper(bean , beanDefinition.getScopeValue()) ;
            return beanWrapper ;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null ;
    }

    @Override
    public boolean removeBeanWrapper(String beanName) {
        BeanWrapper bw = this.factoryBeanInstanceCache.remove(beanName) ;
        return bw != null ;
    }

    @Override
    public BeanWrapper getBeanWrapper(String beanName) {
        return this.factoryBeanInstanceCache.get(beanName) ;
    }

    @Override
    public boolean containsBeanWrapper(String beanName) {
        return this.factoryBeanInstanceCache.containsKey(beanName) ;
    }

    @Override
    public int getBeanWrapperCount() {
        return this.factoryBeanInstanceCache.size() ;
    }

    @Override
    public boolean isBeanWrapperExist(String beanName) {
        return this.containsBeanWrapper(beanName) ;
    }

    @Override
    public String[] getBeanNames() {
        Set<String> beanNames = this.factoryBeanInstanceCache.keySet();
        String[] bns = beanNames.toArray(new String[beanNames.size()]);
        return bns ;
    }
}

7. Autowire

package org.framework.spring.v1.context.bean.support.autowire;

import java.util.List;
import java.util.Map;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/5 23:34
 */
public interface BeanPostProcessor {

    Object getBean(String beanName) ;

    boolean registerBean(String beanName , Object o) ;

    boolean isBeanNameExist(String beanName) ;

    boolean isBeanExist(Object bean) ;

    List<Object> getBeans() ;

    int getBeanCount() ;

    Map<String,Object> getIoc() ;

}

package org.framework.spring.v1.context.bean.support.autowire.abs;

import org.framework.spring.v1.context.bean.support.factory.abs.AbstractSingletonFactoryBean;
import org.framework.spring.v1.context.bean.support.factory.impl.SimpleSingletonFactoryBean;
import org.framework.spring.v1.context.bean.support.autowire.BeanPostProcessor;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/5 23:46
 */

public abstract class AbstractBeanPostProcessor implements BeanPostProcessor {

    protected Map<String,Object> ioc ;

    protected BeanWrapperProcess process ;

    protected AbstractSingletonFactoryBean factoryBean ;

    public AbstractBeanPostProcessor(Map<String, Object> ioc, BeanWrapperProcess beanWrapperProcess , AbstractSingletonFactoryBean factoryBean) {
        this.factoryBean = factoryBean ;
        this.ioc = ioc;
        this.process = beanWrapperProcess;
    }

    public AbstractBeanPostProcessor(BeanWrapperProcess beanWrapperProcess , AbstractSingletonFactoryBean factoryBean) {
        this(new ConcurrentHashMap<String, Object>() , beanWrapperProcess , factoryBean) ;
        init() ;
    }

    public AbstractBeanPostProcessor(BeanWrapperProcess beanWrapperProcess){
        this(new ConcurrentHashMap<String, Object>() , beanWrapperProcess , new SimpleSingletonFactoryBean()) ;
    }

    protected abstract void init();
}

package org.framework.spring.v1.context.bean.support.autowire.impl;

import org.framework.spring.v1.context.annotation.Autowired;
import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;
import org.framework.spring.v1.context.bean.support.factory.impl.SimpleSingletonFactoryBean;
import org.framework.spring.v1.context.bean.support.autowire.abs.AbstractBeanPostProcessor;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;
import org.framework.spring.v1.tools.StringUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/7/5 23:45
 */

public class AnnotationBeanPostProcessor extends AbstractBeanPostProcessor {

    public AnnotationBeanPostProcessor(BeanWrapperProcess beanWrapperProcess) {
        super(beanWrapperProcess , new SimpleSingletonFactoryBean());
    }

    @Override
    protected void init() {
        String[] beanNames = this.process.getBeanNames() ;
        for (String beanName : beanNames) {
            this.registerBean(beanName , this.process.getBeanWrapper(beanName).getWrapperInstance()) ;
        }
    }

    @Override
    public Object getBean(String beanName) {
        return this.ioc.get(beanName) ;
    }

    @Override
    public boolean registerBean(String beanName, Object o) {
        Field[] fields = o.getClass().getDeclaredFields() ;
        for (Field field : fields) {
            if (!field.isAnnotationPresent(Autowired.class)){
                continue ;
            }
            Autowired autowired = field.getAnnotation(Autowired.class) ;
            String autowiredValue ;
            String fieldName = "".equals(autowiredValue = autowired.value().trim())
                        ? StringUtil.toLowerFirstAlp(field.getType().getSimpleName()) : autowiredValue ;
            BeanWrapper bw = this.process.getBeanWrapper(fieldName) ;
            field.setAccessible(true) ;
            try {
                field.set(o , bw.getWrapperInstance()) ;
            } catch (IllegalAccessException e) {
                e.printStackTrace() ;
            }
        }
        //ioc容器注入
        this.ioc.put(beanName,o) ;
        return true ;
    }

    @Override
    public boolean isBeanNameExist(String beanName) {
        return this.ioc.containsKey(beanName) ;
    }

    @Override
    public boolean isBeanExist(Object bean) {
        return this.ioc.containsValue(bean);
    }

    @Override
    public List<Object> getBeans() {
        return new ArrayList<Object>(this.ioc.values()) ;
    }

    @Override
    public int getBeanCount() {
        return this.ioc.size() ;
    }

    @Override
    public Map<String, Object> getIoc() {
        return this.ioc ;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40788718/article/details/107307838