手写spring ,帮助理解spring 实现原理及学习spring源码

目录

1、  自定义一个spring的容器

2  、自定义注解

3、 自定义aware 接口

4、 自定义Servcie

5、 自定义配置,运行类


我看过spring 源码,spring 核心在于 refresh()的13个方法,很多人,包括我,也很好奇是怎么实现的,今天,手写一个简单的spring ,帮助理解。文中所有的代码全是手写的,只依赖一个cglib包。

项目结构:

 1、自定义一个spring的容器

pom.xml文件:

  <dependencies>
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.3.0</version>
    </dependency>
  </dependencies>

刚学pring的时候,都是这样用spring:

        ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml");
        MyCalculator bean = ac.getBean(MyCalculator.class);
        System.out.println(bean.toString());

我们自己实现一个spring容器

package com.hdg.spring.springframework;

import com.hdg.spring.springframework.annotation.*;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HDGApplicationContext {
    private Class configClass;

    private Map<String,HDGBeanDefinition> beanDefinitionMap=new HashMap<>();
    private Map<String,Object> sinigletonObject=new HashMap<>();

    public HDGApplicationContext(Class configClass) {
        //扫描
        scanBean(configClass);

        this.configClass = configClass;
        //创建非懒加载的bean
        for(String beanName : beanDefinitionMap.keySet()){
            HDGBeanDefinition hdgBeanDefinition = beanDefinitionMap.get(beanName);

            if(hdgBeanDefinition.getScope().equals("singleton") && !hdgBeanDefinition.isLazy()){
                Object bean = createBean(beanName, hdgBeanDefinition);
                sinigletonObject.put(beanName,bean);
            }
        }

    }
   public Object createBean(String beanName,HDGBeanDefinition hdgBeanDefinition){
       Class clazz = hdgBeanDefinition.getClazz();
       Object instance = null;
       try {
           instance = clazz.newInstance();
          for(Field field: instance.getClass().getDeclaredFields())  {
              if(field.isAnnotationPresent(HDGAutowired.class)){
                  field.setAccessible(true);
//                  field.set(instance,getBean(field.getName()));
                  field.set(instance,getBean(field.getType()));
              }
          }
          if(instance instanceof  HDGApplicationContextAware){
              ((HDGApplicationContextAware)instance).setApplicationContext(this);
          }
           if(instance instanceof  HDGBeanNameAware){
               ((HDGBeanNameAware)instance).setBeanName(beanName);
           }
           Object target=instance;
           if(clazz.isAnnotationPresent(HDGTransactional.class)){
               Enhancer enhancer=new Enhancer();
               enhancer.setSuperclass(clazz);
               enhancer.setCallback(new MethodInterceptor() {
                   @Override
                   public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                       System.out.println("开户事务");
                       Object result = method.invoke(target, objects);
                       System.out.println("提交事务");
                       return result;
                   }
               });
               instance = enhancer.create();
           }


           return instance;
       } catch (InstantiationException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       }
       return instance;
   }



    private void scanBean(Class configClass) {
        if(configClass.isAnnotationPresent(HDGComponentScan.class)){
            HDGComponentScan annotation = (HDGComponentScan) configClass.getAnnotation(HDGComponentScan.class);
            String path = annotation.value();
            System.out.println("path="+path);//path=com.hdg.spring.user
            path=path.replace(".","/");
            //类加载器:AppClassLoader
            ClassLoader classLoader = this.getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file=new File(resource.getFile());
            List<File> classList=new ArrayList<>();
            if(file.isDirectory()){
//                System.out.println("file="+file);
                for(File listFile:file.listFiles()){
//                    System.out.println(listFile);
                    if(listFile.isDirectory()){
                        for(File f:listFile.listFiles()){
                           if(!f.isDirectory()){
                               classList.add(f);
                           }
                        }
                    }else{
                        classList.add(listFile);
                    }
                }
            }
            for (File file1 :classList) {
//                System.out.println("file1="+file1);
                String absolutePath = file1.getAbsolutePath();
                String className=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"))
                        .replace("\\",".");
//                System.out.println("className="+className);
                try {
//                    Class<?> aClass = classLoader.loadClass("com.hdg.spring.user.service.OrderService");
                    Class<?> aClass = classLoader.loadClass(className);
                    if(aClass.isAnnotationPresent(HDGComponent.class)){
//                        System.out.println("className2="+className);
                        //判断是否多例,懒加载
                        HDGBeanDefinition hdgBeanDefinition=new HDGBeanDefinition();
                        hdgBeanDefinition.setClazz(aClass);
                        if(aClass.isAnnotationPresent(HDGScope.class)){
                            hdgBeanDefinition.setScope(aClass.getAnnotation(HDGScope.class).value());
                        }else{
                            hdgBeanDefinition.setScope("singleton");
                        }
                        String beanName = aClass.getAnnotation(HDGComponent.class).value();
                        if(beanName.isEmpty()){
                            //jdk自带的首字母小写的工具类
                            beanName= Introspector.decapitalize(aClass.getSimpleName());
                        }
                        System.out.println("beanName="+beanName);

                        beanDefinitionMap.put(beanName,hdgBeanDefinition);
                        hdgBeanDefinition.setLazy(aClass.isAnnotationPresent(HDGLazy.class));


                    }
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    //根据类型
   private  Object getBean(Class beanClass){
        for (String beanName:beanDefinitionMap.keySet()){
            HDGBeanDefinition hdgBeanDefinition=beanDefinitionMap.get(beanName);
            if(hdgBeanDefinition.getClazz().equals(beanClass)){
                return getBean(beanName);
            }
        }
        return null;
   }
    public Object getBean(String beanName){
        if(!beanDefinitionMap.containsKey(beanName)){
            throw new NullPointerException();
        }
        HDGBeanDefinition hdgBeanDefinition = beanDefinitionMap.get(beanName);
        if (hdgBeanDefinition.getScope().equals("singleton")) {
            Object bean = sinigletonObject.get(beanName);
            if(bean ==null){
                  bean = createBean(beanName, hdgBeanDefinition);
                  sinigletonObject.put(beanName,bean);
            }
            return bean;
        }else{
            return  createBean(beanName,hdgBeanDefinition);
        }

    }
}

 我们自己定义一个BeanDefinition

package com.hdg.spring.springframework;

public class HDGBeanDefinition {
    private Class clazz;
    private String scope;
    private boolean isLazy;

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public boolean isLazy() {
        return isLazy;
    }

    public void setLazy(boolean lazy) {
        isLazy = lazy;
    }
}

2  、自定义注解

  实现平时用的注解

package com.hdg.spring.springframework.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface HDGAutowired {
    boolean required() default  true;
}

package com.hdg.spring.springframework.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HDGComponent {
    String value() default  "";
}
package com.hdg.spring.springframework.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface HDGComponentScan {

    String value() default "";
}
package com.hdg.spring.springframework.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface HDGLazy {

}

package com.hdg.spring.springframework.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface HDGScope {
//    String value() default "singleton";
    String value() default "";
}

package com.hdg.spring.springframework.annotation;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HDGTransactional {
}

3、自定义aware 接口

   我们自定义aware接口,spring的实现原理,跟我这里差不多

package com.hdg.spring.springframework.aware;

import com.hdg.spring.springframework.HDGApplicationContext;

public interface HDGApplicationContextAware {
    void setApplicationContext(HDGApplicationContext applicationContext);
}
package com.hdg.spring.springframework.aware;

public interface HDGBeanNameAware {
    void  setBeanName(String beanName);
}

 4、自定义Servcie

package com.hdg.spring.user.service;

import com.hdg.spring.springframework.annotation.HDGAutowired;
import com.hdg.spring.springframework.annotation.HDGComponent;
import com.hdg.spring.springframework.annotation.HDGTransactional;

@HDGComponent
@HDGTransactional
public class AOPService {
    @HDGAutowired
    private BService userService;


    public  void test(){
        System.out.println("userService="+userService);
    }
}
package com.hdg.spring.user.service;

import com.hdg.spring.springframework.annotation.HDGComponent;

@HDGComponent
public class AService {
}

package com.hdg.spring.user.service;

import com.hdg.spring.springframework.*;
import com.hdg.spring.springframework.annotation.HDGAutowired;
import com.hdg.spring.springframework.annotation.HDGComponent;
import com.hdg.spring.springframework.annotation.HDGLazy;
import com.hdg.spring.springframework.aware.HDGApplicationContextAware;
import com.hdg.spring.springframework.aware.HDGBeanNameAware;

@HDGComponent
//@HDGScope("prototype")
@HDGLazy
public class BService implements HDGApplicationContextAware, HDGBeanNameAware {
    @HDGAutowired
    private AService xxxx;

    private HDGApplicationContext hdgApplicationContext;

    private String beanName;

    public  void test(){
        System.out.println("orderService="+xxxx);
        System.out.println("hdgApplicationContext="+hdgApplicationContext);
        System.out.println("beanName="+beanName);
    }

    @Override
    public void setApplicationContext(HDGApplicationContext applicationContext) {
        this.hdgApplicationContext=applicationContext;
    }

    @Override
    public void setBeanName(String beanName) {
        this.beanName=beanName;
    }
}

5、自定义配置,运行类

package com.hdg.spring.user;

import com.hdg.spring.springframework.annotation.HDGComponentScan;

@HDGComponentScan("com.hdg.spring.user")
public class APPconfig {
}
package com.hdg.spring.user;

import com.hdg.spring.springframework.HDGApplicationContext;
import com.hdg.spring.user.service.AOPService;

public class MyApplication {
    public static void main(String[] args) {
        HDGApplicationContext applicationContext=new HDGApplicationContext(APPconfig.class);
        AOPService aopService = (AOPService)applicationContext.getBean("AOPService");
        aopService.test();

    }
}

代码就写完了,可以实现spring的简单功能了,spring底层其实也是这样实现的

这里还实现了AOP 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fyihdg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值