手写简易版Spring启动流程

建立一个Maven项目:
手写简易版Spring启动流程_第1张图片
主启动类Main:

public class Main {
    public static void main(String[] args) {

        ZaApplicationContext applicationContext=new ZaApplicationContext(AppConfig.class);
        UserService userService= (UserService) applicationContext.getBean("userService");
//        UserService userService1= (UserService) applicationContext.getBean("userService");
        userService.test();
        System.out.println(userService);
//        System.out.println(userService1);
    }
}

AppConfig:

@ComponentScan("com.test")
public class AppConfig {
}

OrderService:

@Component("orderService")
public class OrderService {
}

UserService:

@Component("orderService")
public class OrderService {
}

User:

public class User {
}

ZaBeanPostProcessor:

@Component
public class ZaBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {

        //        针对某个bean进行特殊处理
        if (beanName.equals("userService")) {
            System.out.println(bean);
            System.out.println("初始化之前");
        }
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {

//        在这里实现AOP
        if (beanName.equals("userService")) {
            System.out.println(bean);
            System.out.println("初始化之后");
        }
        return bean;
    }
}

BeanDefinition:

/**
 * Description:bean属性定义
 * Date: 2022/9/22 16:56
 **/
public class BeanDefinition {
//    bean类型
    private Class clazz;
//    bean作用域
    private String scope;

    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;
    }
}

ZaApplicationContext:

public class ZaApplicationContext {

    private Class configClass;

    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();

    private Map<String,Object> singletonObjects=new HashMap<>();//单例池

    private List<BeanPostProcessor> beanPostProcessorList=new ArrayList<>();

    public ZaApplicationContext(Class configClass){
        this.configClass=configClass;

        Scan(configClass); //扫描  主要功能:生成beanDefinition对象,并把它和beanName一起放到map中

        preInstantiateSingletons(); //实例化单例--->放到单例池中


    }

    private void preInstantiateSingletons() {
        //        在扫描后判断哪些bean是单例的(在Spring启动时将单例bean放到单例池中)
        for(Map.Entry<String,BeanDefinition> entry:beanDefinitionMap.entrySet()){
            BeanDefinition beanDefinition=entry.getValue();
            String beanName=entry.getKey();
            if(beanDefinition.getScope().equals("singleton")){
//                创建bean
                Object bean=createBean(beanName,beanDefinition);
//                存放到单例池中
                singletonObjects.put(beanName,bean);
            }
        }
    }

    private Object createBean(String beanName,BeanDefinition beanDefinition) {

        try {
            //        根据bean的类型得到一个Class对象
            Class clazz=beanDefinition.getClazz();
//            实例化对象
           Object instance=clazz.newInstance();

//           找到bean中所有的属性,然后判断该属性上是否有@Autowired注解(依赖注入)
            for(Field field:clazz.getDeclaredFields()){
                if(field.isAnnotationPresent(Autowired.class)){
//                    给加了@Autowired注解的属性进行赋值
                    String name = field.getName();
                    Object bean=getBean(name);
                    if(bean==null){ //  bean== null && required==true 时 报错

                    }

//                    通过反射方式赋值
                    field.setAccessible(true);
                    field.set(instance,bean);
                }
            }
//            初始化前 遍历beanPostProcessor 执行初始化前方法
            for(BeanPostProcessor beanPostProcessor:beanPostProcessorList){
                instance=beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
            }


//            初始化
            if (instance instanceof InitializingBean) { //判断当前实例对象有没有实现InitializingBean接口
                try {
//                    进行强制类型转换并调用afterPropertiesSet方法
                    ((InitializingBean)instance).afterPropertiesSet();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
//            初始化后 执行初始化后方法
            for(BeanPostProcessor beanPostProcessor:beanPostProcessorList) {
                instance=beanPostProcessor.postProcessAfterInitialization(instance,beanName);
            }
           return instance;

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

    private void Scan(Class configClass) {
        //       1. 解析传递进行来的配置类
        ComponentScan annotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); //拿到配置类上的注解
        String path=annotation.value();//获得配置类上注解的扫描路径 com.test
        path=path.replace(".","/");

//       2.扫描--->找加了Component注解的类(再判断该是单例还是多例)--->生成bean对象
        ClassLoader classLoader=ZaApplicationContext.class.getClassLoader(); // app
//        通过类加载器获取该路径下的资源
        URL resource=classLoader.getResource(path);
//        获取资源中的各个文件
        File file=new File(resource.getFile());
        File[] files=file.listFiles();
//        遍历文件
        for(File f:files){
//            获取文件的绝对路径
            String fileName=f.getAbsolutePath();
            if(fileName.endsWith(".class")){ //判断文件是否以.class结尾
//                截取文件路径的名称 截取后文件以com开头 .class结尾
                String className=fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class"));
//                将路径中的 "\\"用 "." 替换
                className=className.replace("\\",".");
                try {
                    //            把file对象转换成class对象
                    Class clazz=classLoader.loadClass(className);//使用类加载 传递的是类的全限定名(com.test.ClassName)
//                  找到被@Component注解修饰的类
                    if(clazz.isAnnotationPresent(Component.class)){
//                        判断这个类是否实现了BeanPostProcessor接口
                        if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
//                            进行实例化得到一个beanPostProcessor对象
                            BeanPostProcessor o= (BeanPostProcessor) clazz.newInstance();
                            beanPostProcessorList.add(o);

                        }

                        Component annotation1= (Component) clazz.getAnnotation(Component.class);
                        String beanName = annotation1.value(); //获取Component注解中的beanName

                        BeanDefinition beanDefinition=new BeanDefinition();
//                        设置beanDefinition的bean类型---> 就是当前扫描到的对象clazz
                        beanDefinition.setClazz(clazz);
                        if(clazz.isAnnotationPresent(Scope.class)){
//                            有@Scope注解,就把它的值设置到beanDefinition的scope中
                            Scope annotation2= (Scope) clazz.getAnnotation(Scope.class);
                            beanDefinition.setScope(annotation2.value());
                        }else {
//                            没有@Scope注解,就默认是单例
                            beanDefinition.setScope("singleton");
                        }
                        beanDefinitionMap.put(beanName,beanDefinition);
                    }
                }catch (ClassNotFoundException e){
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    public Object getBean(String beanName){ // beanName--->map--->BeanDefinition对象---scope
//        if传来的beanName在map中有对应的value
        if(beanDefinitionMap.containsKey(beanName)){
            BeanDefinition beanDefinition=beanDefinitionMap.get(beanName);
            if(beanDefinition.getScope().equals("singleton")){
//                单例bean
                Object o=singletonObjects.get(beanName);//从单例池中获取bean
                return o;
            }else{
//                多例bean
                Object bean=createBean(beanName,beanDefinition);
                return bean;
            }
        }else {
            throw  new NullPointerException();
        }
    }
}

BeanPostProcessor:

public interface BeanPostProcessor {

     Object postProcessBeforeInitialization(Object bean, String beanName);



     Object postProcessAfterInitialization(Object bean, String beanName);

}

Autowired:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {

    boolean required() default true;

}

Component:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value() default "";

}

ComponentScan:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
    String value()default "";

}

InitializingBean:

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

Scope:

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

Spring中bean自动生成原理:
例如:Spring如何自动生成UserService的bean:
1.先通过无参构造生成UserService对象
2.依赖注入:通过反射来获取UserService上哪些属性上加了@Autowired或者@Resource注解,对加了这些注解的属性进行赋值,也就是依赖注入。
3.然后进行初始化,在初始化之前会先判断有没有方法上添加了@PostConstruct注解,如果加了这个注解,则在初始化前执行这个方法,这个注解可以放在多个方法上;然后在初始化的时候,会执行afterPropertiesSet方法;然后再执行初始化后方法(aop),在此时通过aop生成代理对象。
4.如果没有规定这个bean的范围,则默认是单例bean,则会将生成的bean(代理对象)存放到Map中,key是beanName,value是bean对象,然后放到单例池中。如果不是单例bean,则不用放到Map中和单例池中。

Spring中bean实例化和初始化有什么区别?
bean实例化就是上面的第一步,通过无参构造实例化得到一个对象(这时候对象中的属性还没有值)
bean初始化就是上面的第三步,也就是执行afterPropertiesSet方法进行初始化

判断构造方法:
没有构造方法时,默认使用无参构造;
有一个构造方法时,会直接使用那个构造方法;
当有多个构造方法时(>1),当没有声明要使用哪个构造方法时,必须要显示的写出无参构造,因为Spring的在创建对象时会默认选择无参构造来创建对象,否则会报错(无声明构造and无无参构造)。当声明了使用哪个构造方法时,并且此时还有无参构造,会选择使用我们自己声明的那个构造方法。

构造方法中的入参判断:
手写简易版Spring启动流程_第2张图片
构造方法在单例池中寻找OrderService的bean时先根据type进行匹配,如果OrderService类型的bean只有一个时,就使用这个(name不同也不会报错);
如果OrderService类型的bean有多个时,就再根据它的name进行匹配(没有相匹配的name时会报错)

怎么声明要使用的构造方法呢?
在要使用的构造方法上加上@Autowired注解

单例bean和单例模式区别?
单例bean:一个Spring Bean容器中仅有一个实例,同一个容器中类型相同但是名称不同是不同的实例。一个JVM进程中可能会有多个Bean容器,所以即使是单例bean,在一个JVM进程中也可能会有多个实例
单例模式:一个JVM进程(一个运行的Java程序)中仅有一个实例

你可能感兴趣的:(Spring,spring,java,jvm)