Blade源码深入探索1--注册路由之ioc容器

来源:互联网 发布:死亡扳机2机枪 mac 编辑:程序博客网 时间:2024/05/29 11:56

最近在知乎看到一个GitHub项目,觉得适合自己学习,就打算深入研究,这里是GitHub的地址:https://github.com/biezhi/blade

附带作者大大自己写的说明:https://www.gitbook.com/book/biezhi/blade-in-action/details

依照作者写的教程,可以搭建一个简单的页面,现在开始探索blade源码,从开始注册路由开始解析。。。

根据作者自己的介绍:The Blade is the core operating class of the framework,which can be used to register routes,modify the template engine, set the file list display,static resource directory, and so on.可以知道Blade类是这个框架的核心类,可以注册路由、修改文件引擎、设置静态资源目录之类的操作。其类图大致如下:


先用me()方法创建一个新的Blade对象,blade对象里,有几个重要的属性:

/** * Copyright (c) 2017, biezhi 王爵 (biezhi.me@gmail.com) * <p> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.blade;import com.blade.event.BeanProcessor;import com.blade.event.EventListener;import com.blade.event.EventManager;import com.blade.event.EventType;import com.blade.exception.BladeException;import com.blade.ioc.Ioc;import com.blade.ioc.SimpleIoc;import com.blade.kit.Assert;import com.blade.kit.BladeKit;import com.blade.kit.IOKit;import com.blade.kit.StringKit;import com.blade.mvc.SessionManager;import com.blade.mvc.handler.DefaultExceptionHandler;import com.blade.mvc.handler.ExceptionHandler;import com.blade.mvc.handler.RouteHandler;import com.blade.mvc.handler.WebSocketHandler;import com.blade.mvc.hook.WebHook;import com.blade.mvc.http.HttpMethod;import com.blade.mvc.http.HttpSession;import com.blade.mvc.http.Session;import com.blade.mvc.route.RouteMatcher;import com.blade.mvc.ui.template.DefaultEngine;import com.blade.mvc.ui.template.TemplateEngine;import com.blade.server.Server;import com.blade.server.netty.NettyServer;import lombok.AccessLevel;import lombok.NoArgsConstructor;import lombok.NonNull;import lombok.extern.slf4j.Slf4j;import java.nio.file.Files;import java.nio.file.Paths;import java.util.*;import java.util.concurrent.CountDownLatch;import java.util.function.Consumer;import static com.blade.mvc.Const.*;/** * Blade Core * <p> * The Blade is the core operating class of the framework, * which can be used to register routes, * modify the template engine, set the file list display, * static resource directory, and so on. * * @author biezhi 2017/5/31 */@Slf4j@NoArgsConstructor(access = AccessLevel.PRIVATE)public class Blade {    /**     * Project middleware list,     * the default is empty, when you use the time you can call the use of methods to add.     * <p>     * Blade provide you with BasicAuthMiddleware, CsrfMiddleware,     * you can customize the implementation of some middleware     */    private List<WebHook> middleware = new ArrayList<>();    /**     * BeanProcessor list, which stores all the actions that were performed before the project was started     */    private List<BeanProcessor> processors = new ArrayList<>();    /**     * All need to be scanned by the package, when you do not set the time will scan com.blade.plugin package     */    private Set<String> packages = new LinkedHashSet<>(PLUGIN_PACKAGE_NAME);    /**     * All static resource URL prefixes,     * defaults to "/favicon.ico", "/robots.txt", "/static/", "/upload/", "/webjars/",     * which are located under classpath     */    private Set<String> statics = new HashSet<>(DEFAULT_STATICS);    /**     * The default IOC container implementation     */    private Ioc ioc = new SimpleIoc();    /**     * The default template engine implementation, this is a very simple, generally not put into production     */    private TemplateEngine templateEngine = new DefaultEngine();    /**     * Event manager, which manages all the guys that will trigger events     */    private EventManager eventManager = new EventManager();    /**     * Session manager, which manages session when you enable session     */    private SessionManager sessionManager = new SessionManager();    /**     * Used to wait for the start to complete the lock     */    private CountDownLatch latch = new CountDownLatch(1);    /**     * Web server implementation, currently only netty     */    private Server server = new NettyServer();    /**     * A route matcher that matches whether a route exists     */    private RouteMatcher routeMatcher = new RouteMatcher();    /**     * Blade environment, which stores the parameters of the app.properties configuration file     */    private Environment environment = Environment.empty();    /**     * Exception handling, it will output some logs when the error is initiated     */    private Consumer<Exception> startupExceptionHandler = (e) -> log.error("Start blade failed", e);    /**     * Exception handler, default is DefaultExceptionHandler.     * <p>     * When you need to customize the handling of exceptions can be inherited from DefaultExceptionHandler     */    private ExceptionHandler exceptionHandler = new DefaultExceptionHandler();    /**     * Used to identify whether the web server has started     */    private boolean started = false;    /**     * Project main class, the main category is located in the root directory of the basic package,     * all the features will be in the sub-package below     */    private Class<?> bootClass = null;    /**     * Session implementation type, the default is HttpSession.     * <p>     * When you need to be able to achieve similar RedisSession     */    private Class<? extends Session> sessionImplType = HttpSession.class;    /**     * WebSocket path     */    private String webSocketPath;    /**     * Blade app start banner, default is Const.BANNER     */    private String bannerText;    /**     * Blade app start thread name, default is Const.DEFAULT_THREAD_NAME     */    private String threadName;    /**     * WebSocket Handler     */    private WebSocketHandler webSocketHandler;    /**     * Give your blade instance, from then on will get the energy     *     * @return return blade instance     */    public static Blade me() {        return new Blade();    }    /**     * Get blade ioc container, default is SimpleIoc implement.     * <p>     * IOC container will help you hosting Bean or component, it is actually a Map inside.     * In the blade in a single way to make objects reuse,     * you can save resources, to avoid the terrible memory leak     *     * @return return ioc container     */    public Ioc ioc() {        return ioc;    }    /**     * Add a get route to routes     *     * @param path    your route path     * @param handler route implement     * @return return blade instance     */    public Blade get(@NonNull String path, @NonNull RouteHandler handler) {        routeMatcher.addRoute(path, handler, HttpMethod.GET);        return this;    }    /**     * Add a post route to routes     *     * @param path    your route path     * @param handler route implement     * @return return blade instance     */    public Blade post(@NonNull String path, @NonNull RouteHandler handler) {        routeMatcher.addRoute(path, handler, HttpMethod.POST);        return this;    }    /**     * Add a put route to routes     *     * @param path    your route path     * @param handler route implement     * @return return blade instance     */    public Blade put(@NonNull String path, @NonNull RouteHandler handler) {        routeMatcher.addRoute(path, handler, HttpMethod.PUT);        return this;    }    /**     * Add a delete route to routes     *     * @param path    your route path     * @param handler route implement     * @return return blade instance     */    public Blade delete(@NonNull String path, @NonNull RouteHandler handler) {        routeMatcher.addRoute(path, handler, HttpMethod.DELETE);        return this;    }    /**     * Add a before route to routes, the before route will be executed before matching route     *     * @param path    your route path     * @param handler route implement     * @return return blade instance     */    public Blade before(@NonNull String path, @NonNull RouteHandler handler) {        routeMatcher.addRoute(path, handler, HttpMethod.BEFORE);        return this;    }    /**     * Add a after route to routes, the before route will be executed after matching route     *     * @param path    your route path     * @param handler route implement     * @return return blade instance     */    public Blade after(@NonNull String path, @NonNull RouteHandler handler) {        routeMatcher.addRoute(path, handler, HttpMethod.AFTER);        return this;    }    /**     * Setting blade mvc default templateEngine     *     * @param templateEngine TemplateEngine object     * @return blade     */    public Blade templateEngine(@NonNull TemplateEngine templateEngine) {        this.templateEngine = templateEngine;        return this;    }    /**     * Get TemplateEngine, default is DefaultEngine     *     * @return return TemplateEngine     */    public TemplateEngine templateEngine() {        return templateEngine;    }    /**     * Get RouteMatcher     *     * @return return RouteMatcher     */    public RouteMatcher routeMatcher() {        return routeMatcher;    }    /**     * Register bean to ioc container     *     * @param bean bean object     * @return blade     */    public Blade register(@NonNull Object bean) {        ioc.addBean(bean);        return this;    }    /**     * Register bean to ioc container     *     * @param cls bean class, the class must provide a no args constructor     * @return blade     */    public Blade register(@NonNull Class<?> cls) {        ioc.addBean(cls);        return this;    }    /**     * Add multiple static resource file     * the default provides the static, upload     *     * @param folders static resource directory     * @return blade     */    public Blade addStatics(@NonNull String... folders) {        statics.addAll(Arrays.asList(folders));        return this;    }    /**     * Set whether to show the file directory, default doesn't show     *     * @param fileList show the file directory     * @return blade     */    public Blade showFileList(boolean fileList) {        this.environment(ENV_KEY_STATIC_LIST, fileList);        return this;    }    /**     * Set whether open gzip, default disabled     *     * @param gzipEnable enabled gzip     * @return blade     */    public Blade gzip(boolean gzipEnable) {        this.environment(ENV_KEY_GZIP_ENABLE, gzipEnable);        return this;    }    /**     * Get ioc bean     *     * @param cls bean class type     * @return return bean instance     */    public Object getBean(@NonNull Class<?> cls) {        return ioc.getBean(cls);    }    /**     * Get ExceptionHandler     *     * @return return ExceptionHandler     */    public ExceptionHandler exceptionHandler() {        return exceptionHandler;    }    /**     * Set ExceptionHandler, when you need a custom exception handling     *     * @param exceptionHandler your ExceptionHandler instance     * @return return blade instance     */    public Blade exceptionHandler(ExceptionHandler exceptionHandler) {        this.exceptionHandler = exceptionHandler;        return this;    }    /**     * Get current is developer mode     *     * @return return true is developer mode, else not.     */    public boolean devMode() {        return environment.getBoolean(ENV_KEY_DEV_MODE, true);    }    /**     * Whether encoding setting mode for developers     * The default mode is developers     *     * @param devMode developer mode     * @return blade     */    public Blade devMode(boolean devMode) {        this.environment(ENV_KEY_DEV_MODE, devMode);        return this;    }    public Class<?> bootClass() {        return this.bootClass;    }    /**     * Set whether to enable cors     *     * @param enableCors enable cors     * @return blade     */    public Blade enableCors(boolean enableCors) {        this.environment(ENV_KEY_CORS_ENABLE, enableCors);        return this;    }    /**     * Get blade statics list.     * e.g: "/favicon.ico", "/robots.txt", "/static/", "/upload/", "/webjars/"     *     * @return return statics     */    public Set<String> getStatics() {        return statics;    }    /**     * When set to start blade scan packages     *     * @param packages package name     * @return blade     */    public Blade scanPackages(@NonNull String... packages) {        this.packages.addAll(Arrays.asList(packages));        return this;    }    /**     * Get scan the package set.     *     * @return return packages set     */    public Set<String> scanPackages() {        return packages;    }    /**     * Set to start blade configuration file by default     * Boot config properties file in classpath directory.     * <p>     * Without setting will read the classpath -> app.properties     *     * @param bootConf boot config file name     * @return blade     */    public Blade bootConf(@NonNull String bootConf) {        this.environment(ENV_KEY_BOOT_CONF, bootConf);        return this;    }    /**     * Set the environment variable for global use here     *     * @param key   environment key     * @param value environment value     * @return blade     */    public Blade environment(@NonNull String key, @NonNull Object value) {        environment.set(key, value);        return this;    }    public Environment environment() {        return environment;    }    /**     * Set to start the web server to monitor port, the default is 9000     *     * @param port web server port     * @return blade     */    public Blade listen(int port) {        Assert.greaterThan(port, 0, "server port not is negative number.");        this.environment(ENV_KEY_SERVER_PORT, port);        return this;    }    /**     * Set to start the web server to listen the IP address and port     * The default will listen 0.0.0.0:9000     *     * @param address ip address     * @param port    web server port     * @return blade     */    public Blade listen(@NonNull String address, int port) {        Assert.greaterThan(port, 0, "server port not is negative number.");        this.environment(ENV_KEY_SERVER_ADDRESS, address);        this.environment(ENV_KEY_SERVER_PORT, port);        return this;    }    /**     * The use of multiple middleware, if any     *     * @param middleware middleware object array     * @return blade     */    public Blade use(@NonNull WebHook... middleware) {        if (!BladeKit.isEmpty(middleware)) {            this.middleware.addAll(Arrays.asList(middleware));        }        return this;    }    /**     * Get middleware list     *     * @return return middleware list     */    public List<WebHook> middleware() {        return this.middleware;    }    /**     * Set in the name of the app blade application     *     * @param appName application name     * @return blade     */    public Blade appName(@NonNull String appName) {        this.environment(ENV_KEY_APP_NAME, appName);        return this;    }    /**     * Add a event listener     * When the trigger event is executed eventListener     *     * @param eventType     event type     * @param eventListener event listener     * @return blade     */    public Blade event(@NonNull EventType eventType, @NonNull EventListener eventListener) {        eventManager.addEventListener(eventType, eventListener);        return this;    }    /**     * Get session implements Class Type     *     * @return return blade Session Type     */    public Class<? extends Session> sessionType() {        return this.sessionImplType;    }    /**     * Set session implements Class Type, e.g: RedisSession     *     * @param sessionImplType Session Type implement     * @return return blade instance     */    public Blade sessionType(Class<? extends Session> sessionImplType) {        this.sessionImplType = sessionImplType;        return this;    }    /**     * Event on started     *     * @param processor bean processor     * @return return blade instance     */    public Blade onStarted(@NonNull BeanProcessor processor) {        processors.add(processor);        return this;    }    /**     * Get processors     *     * @return return processors     */    public List<BeanProcessor> processors() {        return processors;    }    /**     * Get EventManager     *     * @return return EventManager     */    public EventManager eventManager() {        return eventManager;    }    /**     * Get SessionManager     *     * @return return SessionManager     */    public SessionManager sessionManager() {        return sessionManager;    }    /**     * Disable session, default is open     *     * @return return blade instance     */    public Blade disableSession() {        this.sessionManager = null;        return this;    }    /**     * Start blade application.     * <p>     * When all the routing in the main function of situations you can use,     * Otherwise please do not call this method.     *     * @return return blade instance     */    public Blade start() {        return this.start(null, null);    }    /**     * Start blade application     *     * @param mainCls main Class, the main class bag is basic package     * @param args    command arguments     * @return return blade instance     */    public Blade start(Class<?> mainCls, String... args) {        return this.start(mainCls, DEFAULT_SERVER_ADDRESS, DEFAULT_SERVER_PORT, args);    }    /**     * Start the blade web server     *     * @param bootClass Start the boot class, used to scan the class in all of the packages     * @param address   web server bind ip address     * @param port      web server bind port     * @param args      launch parameters     * @return blade     */    public Blade start(Class<?> bootClass, @NonNull String address, int port, String... args) {        try {            environment.set(ENV_KEY_SERVER_ADDRESS, address);            Assert.greaterThan(port, 0, "server port not is negative number.");            this.bootClass = bootClass;            eventManager.fireEvent(EventType.SERVER_STARTING, this);            Thread thread = new Thread(() -> {                try {                    server.start(Blade.this, args);                    latch.countDown();                    server.join();                } catch (Exception e) {                    startupExceptionHandler.accept(e);                }            });            String threadName = null != this.threadName ? this.threadName : environment.get(ENV_KEY_APP_THREAD_NAME, null);            threadName = null != threadName ? threadName : DEFAULT_THREAD_NAME;            thread.setName(threadName);            thread.start();            started = true;        } catch (Exception e) {            startupExceptionHandler.accept(e);        }        return this;    }    /**     * Await web server started     *     * @return return blade instance     */    public Blade await() {        if (!started) {            throw new IllegalStateException("Server hasn't been started. Call start() before calling this method.");        }        try {            latch.await();        } catch (Exception e) {            log.error("await error", e);            Thread.currentThread().interrupt();        }        return this;    }    /**     * Stop current blade application     * <p>     * Will stop synchronization waiting netty service     */    public void stop() {        eventManager.fireEvent(EventType.SERVER_STOPPING, this);        server.stopAndWait();        eventManager.fireEvent(EventType.SERVER_STOPPED, this);    }    /**     * Register WebSocket path     *     * @param path    websocket path     * @param handler websocket handler     * @return return blade instance     */    public Blade webSocket(@NonNull String path, @NonNull WebSocketHandler handler) {        if (null != this.webSocketHandler) {            throw new BladeException(500, "There is already a WebSocket path.");        }        this.webSocketPath = path;        this.webSocketHandler = handler;        System.out.println(String.format("\n\t\t\t\t\t\t\t\t\t\t\t\t\t" +                "\t\t\t\t\t Register WebSocket Path: %s\n", path));        return this;    }    /**     * Get webSocket path     *     * @return return websocket path     */    public String webSocketPath() {        return webSocketPath;    }    /**     * Set blade start banner text     *     * @param bannerText banner text     * @return return blade instance     */    public Blade bannerText(String bannerText) {        this.bannerText = bannerText;        return this;    }    /**     * Get banner text     *     * @return return blade start banner text     */    public String bannerText() {        if (null != bannerText) return bannerText;        String bannerPath = environment.get(ENV_KEY_BANNER_PATH, null);        if (StringKit.isNotBlank(bannerPath) && Files.exists(Paths.get(bannerPath))) {            try {                bannerText = IOKit.readToString(bannerPath);            } catch (Exception e) {            }            return bannerText;        }        return null;    }    /**     * Set blade start thread name     *     * @param threadName thread name     * @return return blade instance     */    public Blade threadName(String threadName) {        this.threadName = threadName;        return this;    }    /**     * Get WebSocket Handler     *     * @return return websocket handler     */    public WebSocketHandler webSocketHandler() {        return webSocketHandler;    }}

先分析Blade中构建Ioc容器的过程。在代码第99行中,有一句 private Ioc ioc = new SimpleIoc();

Blade里实现一个默认的ioc容器,将一些默认的对象存储到ioc容器中,再新建一个SimpleIoc对象,其类图如下:



SimpleIoc类

package com.blade.ioc;import com.blade.ioc.bean.BeanDefine;import lombok.extern.slf4j.Slf4j;import java.util.*;/** * The default IOC container implementation * * @author <a href="mailto:biezhi.me@gmail.com" target="_blank">biezhi</a> * @since 1.5 */@Slf4jpublic class SimpleIoc implements Ioc {    private final Map<String, BeanDefine> pool = new HashMap<>(32);    /**     * Add user-defined objects     */    @Override    public void addBean(Object bean) {        addBean(bean.getClass().getName(), bean);    }    /**     * Add user-defined objects     */    @Override    public void addBean(String name, Object bean) {        BeanDefine beanDefine = new BeanDefine(bean);        addBean(name, beanDefine);        // add interface        Class<?>[] interfaces = beanDefine.getType().getInterfaces();        if (interfaces.length > 0) {            for (Class<?> interfaceClazz : interfaces) {                this.addBean(interfaceClazz.getName(), beanDefine);            }        }    }    /**     * Update BeanDefine     */    @Override    public void setBean(Class<?> type, Object proxyBean) {        BeanDefine beanDefine = pool.get(type.getName());        if (beanDefine != null) {            beanDefine.setBean(proxyBean);        } else {            beanDefine = new BeanDefine(proxyBean, type);        }        pool.put(type.getName(), beanDefine);    }    /**     * Register @Bean marked objects     */    @Override    public <T> T addBean(Class<T> type) {        Object bean = addBean(type, true);        return type.cast(bean);    }    @Override    public <T> T getBean(Class<T> type) {        Object bean = this.getBean(type.getName());        try {            return type.cast(bean);        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    @Override    public Object getBean(String name) {        BeanDefine beanDefine = pool.get(name);        if (beanDefine == null) {            return null;        }        return beanDefine.getBean();    }    @Override    public List<BeanDefine> getBeanDefines() {        return new ArrayList<>(pool.values());    }    @Override    public BeanDefine getBeanDefine(Class<?> type) {        return this.getBeanDefine(type, true);    }    @Override    public List<Object> getBeans() {        Set<String>  beanNames = this.getBeanNames();        List<Object> beans     = new ArrayList<>(beanNames.size());        for (String beanName : beanNames) {            Object bean = this.getBean(beanName);            if (null != bean) {                beans.add(bean);            }        }        return beans;    }    @Override    public Set<String> getBeanNames() {        return pool.keySet();    }    @Override    public void remove(String beanName) {        pool.remove(beanName);    }    @Override    public void remove(Class<?> type) {        pool.remove(type.getSimpleName());    }    @Override    public void clearAll() {        pool.clear();    }    /**     * Add user-defined objects     */    private void addBean(String name, BeanDefine beanDefine) {        if (pool.put(name, beanDefine) != null) {            log.warn("Duplicated Bean: {}", name);        }    }    /**     * Register @Bean marked objects     */    private Object addBean(Class<?> type, boolean singleton) {        return addBean(type.getName(), type, singleton);    }    /**     * Register @Bean marked objects     */    private Object addBean(String name, Class<?> beanClass, boolean singleton) {        BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton);        if (pool.put(name, beanDefine) != null) {            log.warn("Duplicated Bean: {}", name);        }        // add interface        Class<?>[] interfaces = beanClass.getInterfaces();        if (interfaces.length > 0) {            for (Class<?> interfaceClazz : interfaces) {                if (null != this.getBean(interfaceClazz)) {                    break;                }                this.addBean(interfaceClazz.getName(), beanDefine);            }        }        return beanDefine.getBean();    }    private BeanDefine getBeanDefine(Class<?> beanClass, boolean singleton) {        try {            Object object = beanClass.newInstance();            return new BeanDefine(object, beanClass, singleton);        } catch (InstantiationException | IllegalAccessException e) {            e.printStackTrace();        }        return null;    }}


其中BeanDefine类定义了一个ioc的目标

package com.blade.ioc.bean;/** * Bean Define, IOC to define a target * * @author <a href="mailto:biezhi.me@gmail.com" target="_blank">biezhi</a> * @since 1.5 */public class BeanDefine {    private Object bean;    private Class<?> type;    private boolean isSingle;    public BeanDefine(Object bean) {        this(bean, bean.getClass());    }    public BeanDefine(Object bean, Class<?> type) {        this.bean = bean;        this.type = type;        this.isSingle = true;    }    public BeanDefine(Object bean, Class<?> type, boolean isSingle) {        this.bean = bean;        this.type = type;        this.isSingle = isSingle;    }    public Object getBean() {        return bean;    }    public void setBean(Object bean) {        this.bean = bean;    }    public Class<?> getType() {        return type;    }    public void setType(Class<?> type) {        this.type = type;    }    public boolean isSingle() {        return isSingle;    }    public void setSignle(boolean isSingle) {        this.isSingle = isSingle;    }}

又因为SimpleIoc类中,私有属性:

private final Map<String, BeanDefine> pool = new HashMap<>(32);

所以在启动的时候,SimpleIoc对象会先创建一个ioc的池子pool,用来实现ioc的存储Bean对象。每个pool里的对象,有三个属性:bean的名称、class类型的type、还是一个布尔值。



接下来再回到Blade中看代码,框架中先注册一个Object对象到ioc容器中,调用SimpleIoc中的addBean(Object bean)方法:

public void addBean(Object bean) {        addBean(bean.getClass().getName(), bean);    }
再调用addBean(String name, Object bean)方法:

public void addBean(String name, Object bean) {        BeanDefine beanDefine = new BeanDefine(bean);        addBean(name, beanDefine);        // add interface        Class<?>[] interfaces = beanDefine.getType().getInterfaces();        if (interfaces.length > 0) {            for (Class<?> interfaceClazz : interfaces) {                this.addBean(interfaceClazz.getName(), beanDefine);            }        }    }
先创建一个BeanDefine对象,然后调用addBean(String name, BeanDefine beanDefine)方法,向一开始定义的IOC容器pool池子中添加用户定义的对象。

再通过for循环获得这个对象所有接口,然后把这些再次用addBean(String name, BeanDefine beanDefine)方法添加进去。

那么这个方法就完成了,继续

接下来又注册一个任意类型的class,调用addBean(Class<T> type)方法:

public <T> T addBean(Class<T> type) {        Object bean = addBean(type, true);        return type.cast(bean);    }
返回通过此Class对象所表示的类或接口调用addBean(Class<?> type, boolean singleton)方法:

private Object addBean(Class<?> type, boolean singleton) {        return addBean(type.getName(), type, singleton);    }
再通过addBean(String name, Class<?> beanClass, boolean singleton)方法:

private Object addBean(String name, Class<?> beanClass, boolean singleton) {        BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton);        if (pool.put(name, beanDefine) != null) {            log.warn("Duplicated Bean: {}", name);        }        // add interface        Class<?>[] interfaces = beanClass.getInterfaces();        if (interfaces.length > 0) {            for (Class<?> interfaceClazz : interfaces) {                if (null != this.getBean(interfaceClazz)) {                    break;                }                this.addBean(interfaceClazz.getName(), beanDefine);            }        }        return beanDefine.getBean();    }
此方法中先调用getBeanDefine(Class<?> beanClass, boolean singleton)方法:

private BeanDefine getBeanDefine(Class<?> beanClass, boolean singleton) {        try {            Object object = beanClass.newInstance();            return new BeanDefine(object, beanClass, singleton);        } catch (InstantiationException | IllegalAccessException e) {            e.printStackTrace();        }        return null;    }
先将一开始从Blade传递过来的Class<?>对象,创建此Class对象所表示的类的新实例再返回一个BeanDefine对象,

再在addBean()方法中,先检验pool中有没有这个bean,然后获取Blade传递过来的Class<?>所有的实例,然后把这些再次用addBean(String name, BeanDefine beanDefine)方法添加进IOC容器的pool池子中去。


这样这个IOC容器就可以完成存储对象的功能,其他的下次再进行分析了。。。

不过从代码中看出作者使用Java反射机制完成设计ioc,改天去研究jvm的反射机制吧。。。

阅读全文
0 0
原创粉丝点击