SSM源码分析之Spring08-手写SpringV2.0

前言

这个小节,我们根据spring源码来进一步封装IOC与AOP源码~

手写SpringV2.0

一切从ApplicationContext上下文开始

spring的ApplicationContext最核心的方法就是refresh了,这个我们之前讲过,所以我这边先预留出来一个refresh方法。

public class GPApplicationContext{

	 public void refresh(){}
	 
}

然后让其实现 BeanFactory

public interface GPBeanFactory {

    /**
     * 根据beanName从IOC容器之中获得一个实例Bean
     * @param beanName
     * @return
     */
    Object getBean(String beanName);

}

得到:

public class GPApplicationContext implements GPBeanFactory {

    private String [] configLocations;

    private GPBeanDefinitionReader reader;

    //用来保证注册式单例的容器
    private Map<String,Object> beanCacheMap = new HashMap<String, Object>();

    //用来存储所有的被代理过的对象
    private Map<String,GPBeanWrapper> beanWrapperMap = new ConcurrentHashMap<String, GPBeanWrapper>();

	
	 public GPApplicationContext(String ... configLocations){
        this.configLocations = configLocations;
        refresh();
    }
	
        //依赖注入,从这里开始,通过读取BeanDefinition中的信息
    //然后,通过反射机制创建一个实例并返回
    //Spring做法是,不会把最原始的对象放出去,会用一个BeanWrapper来进行一次包装
    //装饰器模式:
    //1、保留原来的OOP关系
    //2、我需要对它进行扩展,增强(为了以后AOP打基础)
    @Override
    public Object getBean(String beanName) {

        GPBeanDefinition beanDefinition = this.beanDefinitionMap.get(beanName);

        String className = beanDefinition.getBeanClassName();

        try{

            //生成通知事件
            GPBeanPostProcessor beanPostProcessor = new GPBeanPostProcessor();

            Object instance = instantionBean(beanDefinition);
            if(null == instance){ return  null;}

            //在实例初始化以前调用一次
            beanPostProcessor.postProcessBeforeInitialization(instance,beanName);

            GPBeanWrapper beanWrapper = new GPBeanWrapper(instance);
            beanWrapper.setAopConfig(instantionAopConfig(beanDefinition));
            beanWrapper.setPostProcessor(beanPostProcessor);
            this.beanWrapperMap.put(beanName,beanWrapper);

            //在实例初始化以后调用一次
            beanPostProcessor.postProcessAfterInitialization(instance,beanName);

//            populateBean(beanName,instance);

            //通过这样一调用,相当于给我们自己留有了可操作的空间
            return this.beanWrapperMap.get(beanName).getWrappedInstance();
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }

    private GPAopConfig instantionAopConfig(GPBeanDefinition beanDefinition) throws  Exception{
        GPAopConfig config = new GPAopConfig();
        String expression = reader.getConfig().getProperty("pointCut");
        String[] before = reader.getConfig().getProperty("aspectBefore").split("\\s");
        String[] after = reader.getConfig().getProperty("aspectAfter").split("\\s");

        String className = beanDefinition.getBeanClassName();
        Class<?> clazz = Class.forName(className);

        Pattern pattern = Pattern.compile(expression);

        Class aspectClass = Class.forName(before[0]);
        //在这里得到的方法都是原生的方法
        for (Method m : clazz.getMethods()){

            //public .* com\.gupaoedu\.vip\.spring\.demo\.service\..*Service\..*\(.*\)
            //public java.lang.String com.gupaoedu.vip.spring.demo.service.impl.ModifyService.add(java.lang.String,java.lang.String)
            Matcher matcher = pattern.matcher(m.toString());
            if(matcher.matches()){
                //能满足切面规则的类,添加的AOP配置中
                config.put(m,aspectClass.newInstance(),new Method[]{aspectClass.getMethod(before[1]),aspectClass.getMethod(after[1])});
            }
        }



        return  config;
    }




    //传一个BeanDefinition,就返回一个实例Bean
    private Object instantionBean(GPBeanDefinition beanDefinition){
        Object instance = null;
        String className = beanDefinition.getBeanClassName();
        try{


            //因为根据Class才能确定一个类是否有实例
            if(this.beanCacheMap.containsKey(className)){
                instance = this.beanCacheMap.get(className);
            }else{
                Class<?> clazz = Class.forName(className);
                instance = clazz.newInstance();
                this.beanCacheMap.put(className,instance);
            }

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

        return null;
    }
}

BeanDefinitionReader用对配置文件进行查找,读取、解析

public class GPBeanDefinitionReader {

    private  Properties config = new Properties();

    private List<String> registyBeanClasses = new ArrayList<String>();


    //在配置文件中,用来获取自动扫描的包名的key
    private final String SCAN_PACKAGE = "scanPackage";

    public GPBeanDefinitionReader(String... locations){
        //在Spring中是通过Reader去查找和定位对不对
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));

        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(null != is){is.close();}
            }catch (Exception e){
                e.printStackTrace();
            }

        }

        doScanner(config.getProperty(SCAN_PACKAGE));

    }


    public List<String> loadBeanDefinitions(){
        return this.registyBeanClasses;
    }


    //每注册一个className,就返回一个BeanDefinition,我自己包装
    //只是为了对配置信息进行一个包装
    public GPBeanDefinition registerBean(String className){
        if(this.registyBeanClasses.contains(className)){
            GPBeanDefinition beanDefinition = new GPBeanDefinition();
            beanDefinition.setBeanClassName(className);
            beanDefinition.setFactoryBeanName(lowerFirstCase(className.substring(className.lastIndexOf(".") + 1)));
            return beanDefinition;
        }

        return null;
    }


    //递归扫描所有的相关联的class,并且保存到一个List中
    private void doScanner(String packageName) {

        URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.","/"));

        File classDir = new File(url.getFile());

        for (File file : classDir.listFiles()){
            if(file.isDirectory()){
                doScanner(packageName + "." +file.getName());
            }else {
                registyBeanClasses.add(packageName + "." + file.getName().replace(".class",""));
            }
        }


    }


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



    private String lowerFirstCase(String str){
        char [] chars = str.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

}

BeanDefinition用来存储配置文件中的信息

BeanDefinition相当于保存在内存中的配置

public class GPBeanDefinition {

    private String beanClassName;
    private boolean lazyInit = false;
    private String factoryBeanName;

    public String getBeanClassName() {
        return beanClassName;
    }

    public void setBeanClassName(String beanClassName) {
        this.beanClassName = beanClassName;
    }

    public boolean isLazyInit() {
        return lazyInit;
    }

    public void setLazyInit(boolean lazyInit) {
        this.lazyInit = lazyInit;
    }

    public String getFactoryBeanName() {
        return factoryBeanName;
    }

    public void setFactoryBeanName(String factoryBeanName) {
        this.factoryBeanName = factoryBeanName;
    }

}

BeanWrapper

public class GPBeanWrapper extends GPFactoryBean {

    private GPAopProxy aopProxy = new GPAopProxy();

    public GPBeanPostProcessor getPostProcessor() {
        return postProcessor;
    }

    public void setPostProcessor(GPBeanPostProcessor postProcessor) {
        this.postProcessor = postProcessor;
    }

    //还会用到  观察者  模式
    //1、支持事件响应,会有一个监听
    private GPBeanPostProcessor postProcessor;

    private Object wrapperInstance;
    //原始的通过反射new出来,要把包装起来,存下来
    private Object originalInstance;

    public GPBeanWrapper(Object instance){
        //从这里开始,我们要把动态的代码添加进来了
        this.wrapperInstance = aopProxy.getProxy(instance);
        this.originalInstance = instance;
    }

    public Object getWrappedInstance(){
        return this.wrapperInstance;
    }


    // 返回代理以后的Class
    // 可能会是这个 $Proxy0
    public Class<?> getWrappedClass(){
        return this.wrapperInstance.getClass();
    }


    public void setAopConfig(GPAopConfig config){
        aopProxy.setConfig(config);
    }


    public Object getOriginalInstance() {
        return originalInstance;
    }
}

BeanPostProcessor用做事件监听

public class GPBeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }
    public Object postProcessAfterInitialization(Object bean, String beanName){
        return bean;
    }

}

refresh方法实现定位、加载、注册功能

回到ApplicationContext上下文这个核心类,我们现在实现refresh方法。

    public void refresh(){
        //定位
        this.reader = new GPBeanDefinitionReader(configLocations);

        //加载
        List<String> beanDefinitions = reader.loadBeanDefinitions();

        //注册
        doRegisty(beanDefinitions);


        //依赖注入(lazy-init = false),要是执行依赖注入
        //在这里自动调用getBean方法
        doAutowrited();

//        MyAction myAction = (MyAction)this.getBean("myAction");
//        myAction.query(null,null,"任性的Tom老师");
    }

然后实现注册:

//真正的将BeanDefinitions注册到beanDefinitionMap中

    private void doRegisty(List<String> beanDefinitions) {


        //beanName有三种情况:
        //1、默认是类名首字母小写
        //2、自定义名字
        //3、接口注入
        try {
            for (String className : beanDefinitions) {

                Class<?> beanClass = Class.forName(className);

                //如果是一个接口,是不能实例化的
                //用它实现类来实例化
                if(beanClass.isInterface()){ continue; }

                GPBeanDefinition beanDefinition = reader.registerBean(className);
                if(beanDefinition != null){
                    this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
                }


                Class<?>[] interfaces = beanClass.getInterfaces();
                for (Class<?> i: interfaces) {
                    //如果是多个实现类,只能覆盖
                    //为什么?因为Spring没那么智能,就是这么傻
                    //这个时候,可以自定义名字
                    this.beanDefinitionMap.put(i.getName(),beanDefinition);
                }


                //到这里为止,容器初始化完毕

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

    }

实现自动注入:

    //开始执行自动化的依赖注入
    private void doAutowrited() {


        for(Map.Entry<String,GPBeanDefinition> beanDefinitionEntry : this.beanDefinitionMap.entrySet()){
            String beanName = beanDefinitionEntry.getKey();

            if(!beanDefinitionEntry.getValue().isLazyInit()){
                Object obj = getBean(beanName);
//                System.out.println(obj.getClass());
            }

        }


        for(Map.Entry<String,GPBeanWrapper> beanWrapperEntry : this.beanWrapperMap.entrySet()){

            populateBean(beanWrapperEntry.getKey(),beanWrapperEntry.getValue().getOriginalInstance());

        }

//        System.out.println("===================");


    }



    public void populateBean(String beanName,Object instance){

        Class clazz = instance.getClass();

        //不是所有牛奶都叫特仑苏
        if(!(clazz.isAnnotationPresent(GPController.class) ||
                clazz.isAnnotationPresent(GPService.class))){
            return;
        }


        Field [] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            if (!field.isAnnotationPresent(GPAutowired.class)){ continue; }

            GPAutowired autowired = field.getAnnotation(GPAutowired.class);

            String autowiredBeanName = autowired.value().trim();

            if("".equals(autowiredBeanName)){
                autowiredBeanName = field.getType().getName();
            }

            field.setAccessible(true);

            try {

                //System.out.println("=======================" +instance +"," + autowiredBeanName + "," + this.beanWrapperMap.get(autowiredBeanName));
                field.set(instance,this.beanWrapperMap.get(autowiredBeanName).getWrappedInstance());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }



    }

后记

springV2.0 github地址

发布了47 篇原创文章 · 获赞 5 · 访问量 1853

猜你喜欢

转载自blog.csdn.net/qq_34361283/article/details/104077517
今日推荐