文档章节

创建注入框架(1)

legen_wait_dary
 legen_wait_dary
发布于 2016/10/28 19:17
字数 681
阅读 7
收藏 1

之所以讲jsr330,就是我们要基于这个标准api提供来创建框架。接下来我们就按照这套api一步一步去实现。 首先创建一个maven项目,pom文件内容是:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>zhuru</groupId>
    <artifactId>zhuru</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

我们从底部往前慢慢搭建这个框架,第一个需要创建的类是一个解析class的类,粗布的解决方案比较粗糙,代码如下

ParseClass.java

public class ParseClass<T> {

    private Class<T> tClass;

    private Container container;

    public ParseClass(Class<T> tClass,Container container) {
        this.tClass = tClass;
        this.container = container;
    }

    @SuppressWarnings("unchecked")
    public <K extends T> T newInstance()
            throws IllegalAccessException, InvocationTargetException, InstantiationException {
        if (!container.hasRegisted(tClass)) {
            return null;
        }
        Class<K> implement = container.getImpl(tClass);
        Constructor[] constructors = implement.getConstructors();
        if (constructors.length == 0){
            //没有构造器
            throw new NoConstructorsError();
        }
        T instance = null;
        for (Constructor<K> constructor:constructors) {
            if (constructor.getParameterCount() == 0) {
                instance = constructor.newInstance();
                break;
            }
            if (constructor.isAnnotationPresent(Inject.class)) {
                //获得此构造函数的参数
                Object[] params = new Object[constructor.getParameterCount()];
                int j = 0;
                for (Class z: constructor.getParameterTypes()){
                    Object param = new ParseClass<>(z,container).newInstance();
                    params[j++] = param;
                }
                instance = constructor.newInstance(params);
                break;
            }
        }
        if (instance != null) {
            initFields(instance,implement);
            initMethod(instance,implement);
            return instance;
        }
        return null;
    }

    private <K extends T> void initFields(T instance, Class<K> kClass)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        for (Field field : kClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Inject.class)) {
//                System.out.println(field.getDeclaringClass());
                Object value = new ParseClass<>(field.getType(),container).newInstance();
//                System.out.println(field.getType().isInstance(value));
                field.setAccessible(true);
                field.set(instance,value);
                field.setAccessible(false);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private <K extends T> void initMethod(T instance, Class<K> kClass) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        for (Method method : kClass.getMethods()) {
            if (method.isAnnotationPresent(Inject.class)) {
                Object[] params = new Object[method.getParameterCount()];
                int j = 0;
                for (Class z: method.getParameterTypes()) {
                    params[j++] = new ParseClass<>(z,container).newInstance();
                }
                method.invoke(instance,params);
            }
        }
    }

}

Container.java

public class Container {

    //利用一个容器来存储类
    private Map<Class,Class> mapper;

    public Container() {
        mapper = new HashMap<>();
    }

    public <T,K extends T> void registerClass(Class<T> inter, Class<K> impl) {
        mapper.put(inter,impl);
    }

    @SuppressWarnings("unchecked")
    public <T,K extends T> Class<K> getImpl(Class<T> inter) {
        return mapper.get(inter);
    }

    public boolean hasRegisted(Class inter) {
        return mapper.containsKey(inter);
    }

}

定义了一个异常类:NoConstructorsError.java

public class NoConstructorsError extends RuntimeException {

    public NoConstructorsError() {
        super("没有声明公开的构造器");
    }
}

可以多定义几个异常,弄成RuntimeException,让最终使用用户不用自己去捕获

做了几个测试,还行得通,但有几点需要注意: 第一:封装性不够好,这样很容易出错 第二:对于某些没提供构造函数的类我们无能为力,事实上很多类我们这个都操作不了,这时候需要Provider接口了 第三:每次碰到inject我们都要进行一次构造,对于单例对象来说这个不能满足了。 接下来围绕着三点进行加工。

 

这些文章也同步到了我自己的公众号平台:互联网科技杂谈

© 著作权归作者所有

legen_wait_dary
粉丝 0
博文 10
码字总数 6658
作品 0
荆州
私信 提问
Spring的控制反转和依赖注入

Spring的官网:https://spring.io/ Struts与Hibernate可以做什么事?   Struts,     Mvc中控制层解决方案     可以进行请求数据自动封装、类型转换、文件上传、效验… Hibernate,...

别叫小伙
2017/03/12
0
0
Spring|Spring概述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/darlingwood2013/article/details/89374446 Spring|Spring概述 Spring 介绍 Spring 是一个分层的JavaSE/EE f...

叶晚林
04/19
0
0
Scala下Play框架学习笔记(Actions,Controllers and Results)

Scala下Play框架的学习是一件辛苦的事情,因为该框架比较新,scala语言也较新,所以中文资料很少,经过同事推荐,去了如下英文网站看资料: https://www.playframework.com/documentation/2....

金明略
2016/12/22
0
0
01-SpringIoC&DI-授课

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 https://blog.csdn.net/qq39817135/article/details/97500418 1. spring概述 1.1 Spring是什...

春哥的技术还不行
09/01
0
0
控制反转与依赖注入通俗描述

控制反转(IOC): 由框架或其他某些东西来控制需要调用的事件处理器或其他东西,而不是由业务逻辑决定。 举例:spring中的bean,我们在spring项目中配置了datasource后,不需要关注如何调用它...

李矮矮
2016/09/26
36
0

没有更多内容

加载失败,请刷新页面

加载更多

深入理解表单脚本系列第二篇——表单字段

本文转载于:专业的前端网站➜深入理解表单脚本系列第二篇——表单字段 前面的话   表单字段又叫表单元素,表示表单所包含控件,如<input>、<select>等。本文将详细介绍表单字段的内容 访问...

前端老手
6分钟前
1
0
前端技术之:常用webpack插件

1、html-webpack-plugin Simplifies creation of HTML files to serve your webpack bundles. 主页地址: https://github.com/jantimon/html-webpack-plugin 安装方法: npm i --save-dev h......

popgis
11分钟前
4
0
IT兄弟连 HTML5教程 HTML5表单 多样的输入类型1

HTML5拥有多个新的表单输入类型,这些新特性提供了更好的输入控制和验证。并不是所有的主浏览器都支持新的input类型,不过我们可以在所有的主浏览器中使用它们,即使不被支持,仍然可以显示为...

老码农的一亩三分地
12分钟前
2
0
规则引擎

解决问题 版本迭代速度更不上业务变化,但是若多个业务同时变化,除了为每个业务设计专属配置项也不利于操作。就想服务接口单纯化,将复杂多变的业务逻辑交给规则引擎,让用户在web端或cs端自...

无极之岚
49分钟前
7
0
OSChina 周三乱弹 —— 欢迎你来做产品经理

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :10多次劲歌金曲获奖,更多叱咤歌坛排名,黎明才应该是四大天王之首,只可惜拍的电影太少。单曲循环一个多月的歌,力荐 《无名份的...

小小编辑
今天
557
10

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部