简单模拟Spring框架

参照初始Spring的理解,https://blog.csdn.net/angbug/article/details/120440761,简单模拟Spring框架

/**
 * 模拟Spring框架
 * 1.创建容器:简单实现基本的四个注解
 *     1.1 @ComponentScan 定义扫描的目录范围
 *     1.2 @Component 定义要被Spring管理的class
 *     1.3 @Autowired 定义spring管理的对象需要注入的依赖
 *     1.4 @Scope 定义对象是否单例
 * 2.扫描@ComponentScan定义的目录里的class文件,
 *   2.1把含@Component注解的class包装BeanDefinition,放入BeanDefinition集合
 *      BeanDefinition{className-类名,scope-是否单例}
 *   2.2 把BeanPostProcessor生成实例对象,放入BeanPostProcessor集合
 * 3.遍历BeanDefinition集合,把单例的对象初始化,并放入缓存
 *      3.1 创建对象
 *      3.1 执行 InitializingBean接口功能
 *      3.2 执行 BeanPostProcessor接口功能
 * 4.提供getBean方法,供使用
 * 5 通过BeanPostProcessor和JDK动态代理模拟AOP功能
 */
  1. 四个注解类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}

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

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

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

2.两个功能接口

public interface InitializingBean {
    void afterPropertiesSet();
}

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

3.一个包装class的类定义,这里只简单记录两个属性,类名和是否单例

public class BeanDefinition {
    private Class className;
    private String scope;
    public void setClassName(Class className) {
        this.className = className;
    }
    public Class getClassName() {
        return className;
    }
    public String getScope() {
        return scope;
    }
    public void setScope(String scope) {
        this.scope = scope;
    }
}

4.spring容器

public class ApplicationContextDiy {
    // 配置类
    private Class configClass;
    // BeanDefinition 集合
    private Map<String,BeanDefinition> beanDefinitionMap= new HashMap<>();
    // 生成的单例对象集合
    private Map<String, Object> singletonObjects = new HashMap<>();
    // BeanPostProcessor对象集合
    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    // 1.构造函数
    public ApplicationContextDiy(Class configClass) {
        1. 扫描加载class,把class封装成BeanDefinition,放入BeanDefinition集合
        scan(configClass);
        2.遍历BeanDefinition集合,初始化单例对象,放入缓存
        singletonObjects
    }
    
    // 2.扫描指定目录,加载扫描到的class,并把记录缓存class信息
    public void scan(Class configClass){
        1把含@Component注解的class包装BeanDefinition,放入BeanDefinition集合
         2. 把BeanPostProcessor生成实例对象,放入BeanPostProcessor集合
    }
    
    // 3.创建对象,实际用工厂模式创建
    private Object createBean(String beanName, BeanDefinition beanDefinition){
         1 创建对象
         2 执行 InitializingBean接口功能
         3 执行 BeanPostProcessor接口功能
    }

    // 4.获取bean对象
    public Object getBean(String beanName){
        1 单例直接从缓存里取
        2 原型多例新创建实例bean对象
    }

}

4.1 构造函数

// 1.构造函数
public ApplicationContextDiy(Class configClass) {
    // 获取配置类
    this.configClass = configClass;
    // 扫描加载class,把class封装成BeanDefinition
    scan(configClass);
    // 加载单例非懒加载的对象
    for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
        String beanName = entry.getKey();
        BeanDefinition beanDefinition = entry.getValue();
        if (beanDefinition.getScope().equals("singleton")) {
            Object bean = createBean(beanName, beanDefinition);
            singletonObjects.put(beanName, bean);
        }
    }
}

4.2 扫描指定目录,加载扫描到的class,并把记录缓存class信息

// 2.扫描指定目录,加载扫描到的class,并把记录缓存class信息封装成BeanDefinition
public void scan(Class configClass){
    if (configClass.isAnnotationPresent(ComponentScan.class)) {
        // 获取  ComponentScan配置的扫描目录路径
        ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
        String path = componentScanAnnotation.value();
        path = path.replace(".", "/");
        // 读取扫描目录里的文件
        ClassLoader classLoader = ApplicationContextDiy.class.getClassLoader();
        URL resource = classLoader.getResource(path);

        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
//                    加载class
                String absolutePath = f.getAbsolutePath();
                absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                absolutePath = absolutePath.replace("\\", ".");
                try {
                    Class<?> clazz = classLoader.loadClass(absolutePath);
//                        如果class由Component注解 缓存class信息,等待后面实例化
                    if (clazz.isAnnotationPresent(Component.class)) {
                        Component componentAnnotation = clazz.getAnnotation(Component.class);
                        String beanName = componentAnnotation.value();
                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setClassName(clazz);
                        if (clazz.isAnnotationPresent(Scope.class)) {
                            Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
                            String value = scopeAnnotation.value();
                            beanDefinition.setScope(value);
                        } else {
                            beanDefinition.setScope("singleton");
                        }
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }

                    if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
                        BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
                        beanPostProcessorList.add(instance);
                    }

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

        }
    }
}

4.3 创建对象,实际用工厂模式创建

// 3.简略创建对象,实际用工厂模式创建
private Object createBean(String beanName, BeanDefinition beanDefinition) {
    Class clazz = beanDefinition.getClassName();
    Object instance = null;
    try {
        instance = clazz.getConstructor().newInstance();
//          依赖注入
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                field.set(instance, getBean(field.getName()));
            }
        }
        // 执行 BeanPostProcessor 初始化前置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
        }
        //执行 InitializingBean 初始化方法
        if (instance instanceof InitializingBean) {
            ((InitializingBean)instance).afterPropertiesSet();
        }
        // 执行 BeanPostProcessor 初始化后置方法
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return instance;
}

4.4 获取bean对象

// 4.获取bean对象
public Object getBean(String beanName){
    if (!beanDefinitionMap.containsKey(beanName)) {
        throw new NullPointerException();
    }
    BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
    // 单例直接从缓存里取实例bean对象
    if (beanDefinition.getScope().equals("singleton")) {
        Object singletonBean = singletonObjects.get(beanName);
        if (singletonBean == null) {
            singletonBean = createBean(beanName, beanDefinition);
            singletonObjects.put(beanName, singletonBean);
        }
        return singletonBean;
    } else {
        // 原型多例新创建实例bean对象
        Object prototypeBean = createBean(beanName, beanDefinition);
        return prototypeBean;
    }
}

5 使用BeanPostProcessor和JDK动态代理模拟AOP功能

@Component
public class AopBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if ( "userService".equals(beanName)) {
            Object proxyInstance = Proxy.newProxyInstance(AopBeanPostProcessor.class.getClassLoader(),
                    bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    // 切面
                    Object result = null;
                    if ("test".equals(method.getName())) {
                        System.out.println("userService切面逻辑前");
                        result = method.invoke(bean, args);
                        System.out.println("userService切面逻辑后");
                    }else{
                        result = method.invoke(bean, args);
                    }
                    return result;
                }
            });
            return proxyInstance;
        }
        return bean;
    }
}

6.三个测试类

@Component
public class OrderService {
}

//这里为了简单 使用jdk的动态代理实现AOP必须用接口
public interface UserInterface {
    public void test();
}

@Component
public class UserService  implements UserInterface{
    @Autowired
    public OrderService orderService;
    public void  test(){
        System.out.println("userService test running = " + orderService);
    }
}

7.入口类

@ComponentScan("com.project")
public class MainEnter {
    public static void main(String[] args) {
        // 模拟Spring框架
        ApplicationContextDiy applicationContext = new ApplicationContextDiy(MainEnter.class);

        UserInterface userProxy =  (UserInterface)applicationContext.getBean("userService");
        System.out.println(userProxy);
        userProxy.test();

    }
}

运行结果

com.project.UserService@6537cf78
userService切面逻辑前
userService test running = com.project.OrderService@5afa04c
userService切面逻辑后

Process finished with exit code 0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值