【仿写spring之ioc篇】二、bean生命周期中的创建以及属性赋值

news/2024/5/19 5:44:21 标签: spring, java, 反射, 代理

扫描类

这个类就不多说了,基本所有框架都要有这一步,这里主要关注我们目前要实现的方法,其他的具体方法可以查看源码

isComponent方法

java">	/**
     * 扫描所有带有@Component注解的java类,放入到BeanRegistry
     *
     * @return boolean
     */
    public boolean isComponent(String name) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> clazz = Class.forName(name);
        Component annotation = clazz.getAnnotation(Component.class);
        return annotation != null;
    }

getValuedField方法

java">	/**
     * 获取有value注解的属性
     *
     * @param clazz
     * @return {@link List}<{@link Field}>
     */
    public List<Field> getValuedField(Class<?> clazz){
        List<Field> valuedFieldList = new ArrayList<>();
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            Value annotation = declaredField.getAnnotation(Value.class);
            if (annotation != null){
                valuedFieldList.add(declaredField);
            }
        }
        return valuedFieldList;
    }

工厂类

这个类目前就是用来管理所有的bean对象,存放方式是map,key是beanName,value是bean对象。需要注意的就是扫描到@Value注解时的处理方法,需要通过拼接set的形式来实现

java">package com.ez4sterben.spring.ioc.factory.support;

import com.ez4sterben.spring.ioc.annotation.Value;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * bean工厂,储存所有的bean对象
 *
 * @author ez4sterben
 * @date 2023/08/31
 */
public class BeanFactory {

    /**
     * 储存bean实例
     */
    private final Map<String, Object> beanMap = new HashMap<>(256);

    /**
     * 创建bean
     *
     * @param beanClass
     * @return {@link T}
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public <T> T createBean(Class<T> beanClass) throws InstantiationException, IllegalAccessException {
        return beanClass.newInstance();
    }

    /**
     * 调用set方法
     *
     * @param object
     * @param valuedField
     * @return {@link Object}
     */
    public Object doSet(Object object, List<Field> valuedField) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<?> clazz = object.getClass();
        for (Field field : valuedField) {
            Value annotation = field.getAnnotation(Value.class);
            String value = annotation.value();
            Method method = clazz.getMethod(parseSetter(field.getName()),String.class);
            method.invoke(object,value);
        }
        return object;
    }

    /**
     * 解析set方法
     * @param fieldName
     * @return {@link String}
     */
    public String parseSetter(String fieldName){
        String substring = fieldName.substring(0, 1);
        String s = substring.toUpperCase();
        return "set" + s + fieldName.substring(1);
    }
}

启动类

启动类中打印一下调用赋值方法之后的bean对象看一下效果

java">package com.ez4sterben.spring.test;

import com.ez4sterben.spring.ioc.annotation.BeanScanner;
import com.ez4sterben.spring.ioc.factory.aware.ApplicationContextAware;
import com.ez4sterben.spring.ioc.factory.aware.BeanFactoryAware;
import com.ez4sterben.spring.ioc.factory.aware.BeanNameAware;
import com.ez4sterben.spring.ioc.factory.support.BeanFactory;

import java.lang.reflect.Field;
import java.util.List;

/**
 * 主要
 *
 * @author ez4sterben
 * @date 2023/09/01
 */
public class Main {

    public static void main(String[] args) throws Exception {
        // 1.调用扫描类,加载所有bean
        BeanScanner beanScanner = new BeanScanner();
        BeanFactory beanFactory = new BeanFactory();
        List<String> allJavaFile = beanScanner.getAllJavaFile("F:\\projects\\gitProject\\spring-all\\src\\main\\java\\com\\ez4sterben\\spring\\test");
        // 2.判断是否有Component
        for (String name : allJavaFile) {
            if (beanScanner.isComponent(name)) {
                // 3.是Component就开始bean的生命周期
                Class<?> clazz = beanScanner.getClazz(name);
                // 创建bean
                Object bean = beanFactory.createBean(clazz);
                // 查看@Value注解
                // 1.找到所有@Value的字段
                List<Field> valuedField = beanScanner.getValuedField(clazz);
                // 2.调用set方法
                beanFactory.doSet(bean, valuedField);
                System.out.println(bean);
                // Aware
                // 1.检查是否实现了Aware接口
                // BeanNameAware

                // BeanFactoryAware

                // ApplicationContextAware

                // BeanPostProcessor

                // @PostConstruct

                // InitializingBean

                // BeanPostProcessor

                // using
            }
        }

    }
}

测试类

java">package com.ez4sterben.spring.test;

import com.ez4sterben.spring.ioc.annotation.Component;
import com.ez4sterben.spring.ioc.annotation.Value;
import com.ez4sterben.spring.ioc.factory.aware.BeanNameAware;
import lombok.Data;

/**
 * 测试组件
 *
 * @author ez4sterben
 * @date 2023/09/01
 */
@Component
@Data
public class TestComponent implements BeanNameAware {
    @Value("ez4sterben")
    private String name;
    private String age;

}

测试结果

在这里插入图片描述
可以看到我们成功的给对象赋值了


http://www.niftyadmin.cn/n/4992219.html

相关文章

微软表示Visual Studio的IDE即日起开启“退休”倒计时

据了解&#xff0c;日前有消息透露称&#xff0c;适用于 Mac平台的Visual Studio集成开发环境(IDE)于8月31日启动“退休”进程。 而这意味着Visual Studio for Mac 17.6将继续支持12个月&#xff0c;一直到2024年8月31日。    微软表示后续不再为Visual Studio for Mac开发…

暴力枚举之火柴数

P1149 [NOIP2008 提高组] 火柴棒等式 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 这题有点小坑&#xff0c;我初次做数据开小了。 我们要用已有火柴数来拼数字&#xff0c;由于我们不清楚可以拼成几位数字&#xff0c;所以我们可以开始模拟&#xff0c;但是暴力枚举来模拟…

目录扫描+JS文件中提取URL和子域+403状态绕过+指纹识别(dirsearch_bypass403)

dirsearch_bypass403 在安全测试时&#xff0c;安全测试人员信息收集中时可使用它进行目录枚举&#xff0c;目录进行指纹识别&#xff0c;枚举出来的403状态目录可尝试进行绕过&#xff0c;绕过403有可能获取管理员权限。不影响dirsearch原本功能使用 运行流程 dirsearch进行…

Scala的集合操作之可变数组和不可变数组,可变List集合与不可变List集合,可变Set与不可变Set操作,可变和不可变Map集合和元组操作

Scala的集合操作之&#xff0c;可变数组和不可变数组&#xff0c;可变List集合与不可变List集合 不可变数组 /* traversable/ˈtrvəsəbl/adj.能越过的&#xff1b;可否认的*/ object Test01_ImmutableArray {def main(args: Array[String]): Unit {// 1. 创建数组val arr:…

Nginx 部署 配置

一.概述 什么是nginx? Nginx (engine x) 是一款轻量级的Web 服务器 、反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。 什么是反向代理&#xff1f; 反向代理&#xff08;Reverse Proxy&#xff09;方式是指以代理服务器来接受internet上的连接请求…

ArcGIS Maps SDK for JS(二):MapView简介----创建2D地图

文章目录 1 AMD 引用 ArcGIS Maps SDK for JavaScript2 加载相应模块3 创建地图4 创建 2D 视图 view5 确定页面内容6 CSS 样式7 完整代码 本教程使用 AMD 模块&#xff0c;指导您如何在二维地图视图中创建一个简单的地图。 1 AMD 引用 ArcGIS Maps SDK for JavaScript 在 <…

2023年Java核心技术第十二篇(篇篇万字精讲)

目录 22. AtomicInteger 底层实现原理是什么&#xff1f;如何在自己的项目代码中应用CAS操作&#xff1f; 22.1 典型回答 22.1.1 CAS详细解释&#xff1a; 22.1.1.1 预期值的选取&#xff1a; 22.1.2 CAS的弊端 22.1.2.1 ABA问题&#xff1a; 22.1.2.2 自旋次数限制&#xff1a…

Android 进阶——图形显示系统之VSync和 Choreographer的创建详解(一)

引言 前一篇文章Android 进阶——图形显示系统之底层图像显示原理小结(一)介绍了关于Android 图形显示系统的基础理论,相信你对于Android的图形显示系统中图形界面渲染刷新机制有了更深的了解,接下来进一步讲解VSync和Choreography的联系和作用。 一、VSync 信号的产生概…