模拟Spring中Bean的加载

最近看了一些关于Spring的书籍,结合网上的相关案列,模拟一下Spring的Bean加载的过程

1 模拟Spring的加载环境

1 添加自定义的相关注解

Component注解

在类上使用, 将类注册到中,并且可以指定名称,默认为类名小写.

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

    String value();

}
ComponentScan注解

扫描指定路径, 得到路径下所有的class文件

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

    String value() default "";

}
Scope注解

Bean对象的作用域,默认是单例的

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

    String value() default "singleton";

}
BeanDefinition类

Bean对象的定义类,用来定义对象和作用范围的.

public class BeanDefinition {

    private Class aClass;
    private String scope;

    public Class getaClass() {
        return aClass;
    }

    public void setaClass(Class aClass) {
        this.aClass = aClass;
    }

    public String getScope() {
        return scope;
    }

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

环境上下文对象,负责添加和获取Bean对象到容器.

public class ApplicationContext {

    private ConcurrentHashMap<String, Object> singletonMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

    public ApplicationContext(Class aClass) {

        // 1 获取componentScan注解上的扫描路径
        ComponentScan componentScan = (ComponentScan) aClass.getDeclaredAnnotation(ComponentScan.class);
        String value = componentScan.value().replace(".", "/");
        String path = aClass.getClassLoader().getResource(value).getPath();
        // 2 获取路径下所有class文件
        List<File> fileList = FileUtils.getFileList(path);

        // 3 将注入的Bean对象放到beanDefinitionMap容器中
        fileList.forEach(file -> {
                    // 得到每个文件的路径
                    String filePath = file.getPath();
                    // 得到类路径  (indexOf方法包头不包尾)
                    String classPath = filePath.substring(filePath.indexOf("classes") + 8, filePath.indexOf(".class")).replace("\\", ".");

                    try {
                        // 4 将每个Class对象添加到容器中
                        BeanDefinition beanDefinition = new BeanDefinition();
                        BeanDefinition beanDefinition = new BeanDefinition();
                        Class cla = Class.forName(classPath);
                        if (cla.isAnnotationPresent(Component.class)) {
                            Component component = (Component) cla.getDeclaredAnnotation(Component.class);
                            String className = component.value();
                            beanDefinition.setaClass(cla);
                            if (cla.isAnnotationPresent(Scope.class)) {
                                Scope scope = (Scope) cla.getDeclaredAnnotation(Scope.class);
                                beanDefinition.setScope(scope.value());
                            } else {
                                beanDefinition.setScope("singleton");
                            }
                            beanDefinitionMap.put(className, beanDefinition);
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
        );

    }

    /**
     * 根据Bean名称获取对象
     *
     * @param beanName
     * @return
     */
    public Object getBean(String beanName) {

        Object o = null;
        try {
            if (beanDefinitionMap.containsKey(beanName)) {
                BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
                // 多例
                if ("prototype".equals(beanDefinition.getScope())) {
                    o = beanDefinition.getaClass().newInstance();
                } else if (singletonMap.containsKey(beanName)) {
                    // 单例 且容器中已存在
                    o = singletonMap.get(beanName);
                } else {
                    // 单例 且容器中不存在
                    o = beanDefinition.getaClass().newInstance();
                    singletonMap.put(beanName, o);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("找不到相应的 Bean 对象");
        }

        return o;
    }
    
}

2 添加相关的测试类

ConfigDemo类

给上下文对象使用,获取其注解路径,扫描路径,并注册相关的Bean对象

@ComponentScan("com.cf.service")
public class ConfigDemo {
}
UserService类

用户类接口,供测试使用

package com.cf.service;
public interface UserService {

    Integer getUserSum();

}
OrgService类

组织类接口,供测试使用

package com.cf.service;
public interface OrgService {

    Integer getOrgSum();

}
UserServiceImpl类

用户接口的实现类,供测试使用

@Component("user")
public class UserServiceImpl implements UserService {
    @Override
    public Integer getUserSum() {
        Integer count = 100;
        System.out.println("总共有 " + count + " 个用户");
        return count;
    }
}
OrgServiceImpl类

组织接口的实现类,供测试使用

@Component("org")
@Scope("prototype")
public class OrgServiceImpl implements OrgService {
    @Override
    public Integer getOrgSum() {
        Integer count = 50;
        System.out.println("总共有 " + count + " 个组织");
        return count;
    }
}
SpringTest类

测试类

public class SpringTest {

    public static void main(String[] args) {

        ApplicationContext applicationContext = new ApplicationContext(ConfigDemo.class);

        Object user = applicationContext.getBean("user");
        Object user2 = applicationContext.getBean("user");
        Object org = applicationContext.getBean("org");
        Object org2 = applicationContext.getBean("org");

        System.out.println(user);
        System.out.println(user2);
        System.out.println(org);
        System.out.println(org2);
    }
}
执行结果
/*
    com.cf.service.impl.UserServiceImpl@2d98a335
    com.cf.service.impl.UserServiceImpl@2d98a335
    com.cf.service.impl.OrgServiceImpl@16b98e56
    com.cf.service.impl.OrgServiceImpl@7ef20235
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值