文档章节

我的IOC原理实现——使用注解读取元数据

啦啦啦拉拉
 啦啦啦拉拉
发布于 2016/08/29 20:41
字数 592
阅读 30
收藏 0

我的个人博客

IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中实例化的对象,应用程序由IOC容器进行组装。

以往一般使用基于XML配置文件进行配置元数据,Spring与配置文件完全解耦。但是编写XML定义读取实在是过于繁琐,所以近来都倾向使用注解配置。

模仿 Spring Boot 对目录下的包进行扫描,读取Bean注解的就通过反射将它实例化,字段value注解就对字段赋值。

实例为均为单例模式,暂时未考虑到多线程冲突的情况。

画成这样了

                           instanite              
+---------------------+                +-------+  
|WinterBootApplication|  +--------->   |  Car  |  
+------+-------------++                +---+---+  
       |             |                     ^      
       |             |          set value  |      
       | read file   |                     |      
       |             |                 +---+----+ 
       v             +---------------> |  @Bean | 
                     | read annotation +--------+ 
   +-----------+     |                            
   | Car.class |     |                            
   +-----------+     |                 +---------+
                     +---------------> |  @Value |
                                       +---------+

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

}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Value {
    String value();
}

@Bean
class Car {
    @Value("beetle")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Car{");
        sb.append("name='").append(name).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

class MyApplication {
    public static void main(String[] args) {
        WinterBootApplication.run(MyApplication.class);
        Car car = (Car) WinterBootApplication.getBean("me.zonghua.spring.concept.ioc.Car");
        Log.d(car);
    }

}

public class WinterBootApplication {
    static Map<String, Object> bucket = new HashMap<String, Object>();
    static List<String> classFilePaths = new ArrayList<String>();

    /**
     * 首字母大写的最优方法
     *
     * @param name
     * @return
     */
    static String captureName(String name) {
        char[] cs = name.toCharArray();
        cs[0] -= 32;
        return String.valueOf(cs);
    }

    static void readClassName(File file) {
        String fileName = file.getName();
        if (file.isDirectory()) {
            File[] files = file.listFiles(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    if (name.endsWith(".class") && !name.contains("$")) {
                        return true;
                    } else {
                        return false;
                    }
                }
            });
            for (File fileItem : files) {
                readClassName(fileItem);//递归读取类文件
            }
        } else if (file.isFile() && fileName.endsWith(".class") && !fileName.contains("$")) {
            classFilePaths.add(file.getPath());
        }
    }

    static void loadClass(String className) {
        try {
            Class<?> beanClass = Class.forName(className);
            Bean beanAnnotation = beanClass.getAnnotation(Bean.class);

            if (beanAnnotation != null) {//更改有Bean注解的类
                Object bean = beanClass.newInstance();
                Field[] fields = beanClass.getDeclaredFields();//获取所有声明的字段
                for (Field field : fields) {
                    Value valueAnnotation = field.getAnnotation(Value.class);
                    if (valueAnnotation != null) {
                        String value = valueAnnotation.value();
                        String fieldName = field.getName();
                        String setMethodName = "set" + captureName(fieldName);//获取set方法名
                        Log.d("setMethod : " + setMethodName + "(" + value + ")");
                        Method setMethod = beanClass.getMethod(setMethodName, String.class);
                        setMethod.invoke(bean, value);//动态执行
                    }
                }
                bucket.put(className, bean);//存放到容器
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void run(Class clazz) {
        String rootFilePath = clazz.getResource("").getFile();
        String classPath = clazz.getClassLoader().getResource("").getPath();
        classPath = classPath.replace("/", "\\").substring(1, classPath.length() - 1);
        File rootFile = new File(rootFilePath);
        readClassName(rootFile);
        for (String classFilePath : classFilePaths) {
            String className = classFilePath.replace(classPath, "")
                    .replace(".class", "")
                    .replace("\\", ".");
            className = className.substring(1, className.length());
            loadClass(className);
        }
    }

    public static Object getBean(String className) {
        return bucket.get(className);//通过其他设置,可以实现懒加载或者多次实例化而不是单例
    }
}

运行结果

setMethod : setName(beetle)
Car{name='beetle'}

© 著作权归作者所有

共有 人打赏支持
啦啦啦拉拉
粉丝 4
博文 1
码字总数 592
作品 0
广州
程序员
java annotation与AOP点滴积累

spring注解,与依赖注入 (1).类级别的注解:如@Component、@Repository、@Controller 、@Service 以及JavaEE6的@ManagedBean和@Named注解,都是添加在类上面的类级别注解,Spring容器根据注解...

浮云过眼
2016/03/16
72
0
手把手教你实现Spring ioc

手把手教你实现Spring ioc “Don’t call us, we’ll call you(不要联系我,我会主动联系你)” 这是好莱坞很经典的一句话,应用在ioc(控制反转)领域,发现理解起来相得益彰——你作为用户...

loda0128
2015/06/11
0
0
Spring核心——JSR250与资源控制

JSR-175与元编程 要说明JSR-250先要解释清楚JSR-175,要解释清楚JSR就的先了解JCP是什么。网上资料很多,就不细说了,简单的说JCP(Java Community Process)是管理Java生态(包括J2SE、J2E...

随风溜达的向日葵
07/18
0
0
Java 注解 Annotation

概述 了解 Java 注解前必须先了解元注解。 元注解:描述注解的注解。 如果明白元数据概念就比较好理解元注解 元数据:描述数据的数据。 还是比较抽象哈,下面举个例子说明下。 比如一个txt文...

jijs
2017/12/06
0
0
Spring核心——Stereotype组件与Bean扫描

在注解自动装载中介绍了通过注解(Annotation)自动向Bean中注入其他Bean的方法,本篇将介绍通过注解(Annotation)向容器添加Bean的方法。 Spring的核心容器提供了@Component和@Bean注解来标...

随风溜达的向日葵
07/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Bytom资产发行与部署合约教程

比原项目仓库: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom 发行资产 在比原链上发行资产比较方便快捷,使用节点的dashboard图形界面...

比原链Bytom
26分钟前
1
0
Ext ComboBox 实现下拉多选,全选,反选

Ext ComboBox下拉选中-全选反选逻辑处理 Ext ComboBox 实现下拉多选,全选,反选 方法一: 代码 var me = this;var isMultiSelect = true;//是否设置为下拉多选me.selectValues = [];//保存...

javaART
29分钟前
1
0
Swoole Windows 版(4.2.1)

https://pan.baidu.com/s/1uTm77_cp4kn0_xMgO1DpIw Swoole Windows 版(内部版本,swoole-4.2.1,php-7.1,必须为64位系统,Win7或更高版本)。 解压后,将 $dir/bin 目录,设置到 系统的环境...

老查
32分钟前
1
0
美团点评上市受追捧,成中国第四大互联网企业

从建立到上市,蔚来用了不到4年,拼多多3年,趣头条更是仅用了2年3个月。在这波中概股上市浪潮中,等待了漫长8年的美团点评也终于迎来登陆资本市场的时刻。20日上午,美团创始人兼CEO王兴终于...

Mr_zebra
33分钟前
1
0
Mysql-mybatis批量插入

话不多说直接上代码吧 <insert id="batchSave" >insert into table_name (`name`,age)values<foreach collection="list" index="index" item="item" open="(" separator="," close=......

落叶清风
38分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部