<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手寫Spring框架之IOC

          共 12220字,需瀏覽 25分鐘

           ·

          2020-08-26 21:09


          簡介


          本篇博客主要實現(xiàn)兩個功能: Bean容器 和 IOC.


          Bean容器


          Bean容器也就是Spring容器, 在學(xué)習完Spring之后, 如果要我們用一句話來形容Spring, 我們經(jīng)常會說: Spring是一個容器, 管理著應(yīng)用中所有bean的裝配和生命周期. 從這句話中就可以看出Spring容器的重要性, Spring容器其實是一個Map映射, 里面存儲了應(yīng)用中所有bean的實例, key為該bean實例的Class對象. Spring有兩種容器, 分別是 BeanFactory 和 ApplicationContext, 二者的區(qū)別在于, BeanFactory采用延遲加載策略, 在第一次調(diào)用getBean()時才真正裝配該對象. 而 ApplicationContext會在應(yīng)用啟動時就把所有對象一次性全部裝配好.


          handwritten-mvc-framwork 框架的bean容器是一個 ApplicationContext 式的容器.


          IOC


          IOC的實現(xiàn)思路如下:


          • 首先有一個配置文件定義了應(yīng)用的基礎(chǔ)包, 也就是Java源碼路徑.

          • 讀取基礎(chǔ)包名, 然后通過類加載器獲取到應(yīng)用中所有的Class對象, 存儲到一個集合中.

          • 獲取應(yīng)用中所有Bean (Controller和Service) 的Class對象, 通過反射創(chuàng)建實例, 然后存儲到 Bean容器中.

          • 遍歷Bean容器中的所有Bean, 為所有帶 @Autowired 注解的屬性注入實例.

          • IOC操作要在應(yīng)用啟動時就完成, 所以必須寫在靜態(tài)代碼塊中.


          handwritten-mvc-framwork 實現(xiàn)


          定義注解


          (1) 處理器注解


          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface?Controller {
          }


          (2) 處理器方法注解


          @Target(ElementType.METHOD)
          @Retention(RetentionPolicy.RUNTIME)
          public?@interface?RequestMapping {

          ????/**
          ?????* 請求路徑
          ?????* @return
          ?????*/

          ????String?value() default?"";

          ????/**
          ?????* 請求方法
          ?????* @return
          ?????*/

          ????RequestMethod method() default?RequestMethod.GET;
          }

          //請求方法枚舉類
          public?enum?RequestMethod {
          ????GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
          }


          (3) 依賴注入注解


          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface?Autowired {
          }


          (4) 業(yè)務(wù)類注解


          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface?Service {
          }


          配置文件


          handwritten-mvc-framwork 框架是不存在配置文件的, 配置文件是用戶需要自定義一些配置項, 所以創(chuàng)建一個配置文件, 而框架需要做的就是讀取用戶自定義的配置文件, 如果用戶沒有配置, 就使用默認的配置. handwritten-mvc-example 實例中的一個配置文件如下:


          #數(shù)據(jù)源
          handwritten.framework.jdbc.driver=com.mysql.jdbc.Driver
          handwritten.framework.jdbc.url=jdbc:mysql://localhost:3306/tyshawn_test
          handwritten.framework.jdbc.username=root
          handwritten.framework.jdbc.password=123

          #
          java源碼路徑
          handwritten.framework.app.base_package=com.tyshawn
          #jsp頁面路徑
          handwritten.framework.app.jsp_path=/WEB-INF/view/
          #靜態(tài)資源路徑
          handwritten.framework.app.asset_path=/asset/


          那 handwritten-mvc-framwork 框架如何來加載用戶自定義的配置文件呢?


          (1) ConfigConstant 常量接口


          首先我們要定義一個名為 ConfigConstant 的常量接口, 讓它來維護配置文件中相關(guān)的配置項名稱, 代碼如下:


          public?interface?ConfigConstant {
          ????//配置文件的名稱
          ????String?CONFIG_FILE = "handwritten.properties";

          ????//數(shù)據(jù)源
          ????String?JDBC_DRIVER = "handwritten.framework.jdbc.driver";
          ????String?JDBC_URL = "handwritten.framework.jdbc.url";
          ????String?JDBC_USERNAME = "handwritten.framework.jdbc.username";
          ????String?JDBC_PASSWORD = "handwritten.framework.jdbc.password";

          ????//java源碼地址
          ????String?APP_BASE_PACKAGE = "handwritten.framework.app.base_package";
          ????//jsp頁面路徑
          ????String?APP_JSP_PATH = "handwritten.framework.app.jsp_path";
          ????//靜態(tài)資源路徑
          ????String?APP_ASSET_PATH = "handwritten.framework.app.asset_path";
          }


          (2) PropsUtil 工具類


          然后使用 PropsUtil 工具類來讀取屬性文件


          public?final class?PropsUtil?{

          ????private?static?final Logger LOGGER = LoggerFactory.getLogger(PropsUtil.class);

          ????/**
          ?????* 加載屬性文件
          ?????*/

          ????public?static?Properties loadProps(String fileName) {
          ????????Properties props = null;
          ????????InputStream is?= null;
          ????????try?{
          ????????????is?= ClassUtil.getClassLoader().getResourceAsStream(fileName);
          ????????????if?(is?== null) {
          ????????????????throw?new?FileNotFoundException(fileName + " file is not found");
          ????????????}
          ????????????props = new?Properties();
          ????????????props.load(is);
          ????????} catch?(IOException e) {
          ????????????LOGGER.error("load properties file failure", e);
          ????????} finally?{
          ????????????if?(is?!= null) {
          ????????????????try?{
          ????????????????????is.close();
          ????????????????} catch?(IOException e) {
          ????????????????????LOGGER.error("close input stream failure", e);
          ????????????????}
          ????????????}
          ????????}
          ????????return?props;
          ????}

          ????/**
          ?????* 獲取 String 類型的屬性值(默認值為空字符串)
          ?????*/

          ????public?static?String getString(Properties props, String key) {
          ????????return?getString(props, key, "");
          ????}

          ????/**
          ?????* 獲取 String 類型的屬性值(可指定默認值)
          ?????*/

          ????public?static?String getString(Properties props, String key, String defaultValue) {
          ????????String value?= defaultValue;
          ????????if?(props.containsKey(key)) {
          ????????????value?= props.getProperty(key);
          ????????}
          ????????return?value;
          ????}

          ????/**
          ?????* 獲取 int 類型的屬性值(默認值為 0)
          ?????*/

          ????public?static?int?getInt(Properties props, String key) {
          ????????return?getInt(props, key, 0);
          ????}

          ????/**
          ?????* 獲取 int 類型的屬性值(可指定默認值)
          ?????*/

          ????public?static?int?getInt(Properties props, String key, int?defaultValue) {
          ????????int?value?= defaultValue;
          ????????if?(props.containsKey(key)) {
          ????????????value?= Integer.parseInt(props.getProperty(key));
          ????????}
          ????????return?value;
          ????}

          ????/**
          ?????* 獲取 boolean 類型屬性(默認值為 false)
          ?????*/

          ????public?static?boolean getBoolean(Properties props, String key) {
          ????????return?getBoolean(props, key, false);
          ????}

          ????/**
          ?????* 獲取 boolean 類型屬性(可指定默認值)
          ?????*/

          ????public?static?boolean getBoolean(Properties props, String key, boolean defaultValue) {
          ????????boolean value?= defaultValue;
          ????????if?(props.containsKey(key)) {
          ????????????value?= Boolean.parseBoolean(props.getProperty(key));
          ????????}
          ????????return?value;
          ????}
          }


          (3) ConfigHelper 助手類


          最后借助 PropsUtil 工具類來實現(xiàn) ConfigHelper 助手類, 框架通過 ConfigHelper 類就可以加載用戶自定義的配置文件了, 從代碼中可以看到, 部分配置項擁有默認值, 當用戶沒有自定義時將會使用默認配置.


          public?final class?ConfigHelper?{

          ????/**
          ?????* 加載配置文件的屬性
          ?????*/

          ????private?static?final Properties CONFIG_PROPS = PropsUtil.loadProps(ConfigConstant.CONFIG_FILE);

          ????/**
          ?????* 獲取 JDBC 驅(qū)動
          ?????*/

          ????public?static?String getJdbcDriver()?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_DRIVER);
          ????}

          ????/**
          ?????* 獲取 JDBC URL
          ?????*/

          ????public?static?String getJdbcUrl()?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_URL);
          ????}

          ????/**
          ?????* 獲取 JDBC 用戶名
          ?????*/

          ????public?static?String getJdbcUsername()?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_USERNAME);
          ????}

          ????/**
          ?????* 獲取 JDBC 密碼
          ?????*/

          ????public?static?String getJdbcPassword()?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_PASSWORD);
          ????}

          ????/**
          ?????* 獲取應(yīng)用基礎(chǔ)包名
          ?????*/

          ????public?static?String getAppBasePackage()?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_BASE_PACKAGE);
          ????}

          ????/**
          ?????* 獲取應(yīng)用 JSP 路徑
          ?????*/

          ????public?static?String getAppJspPath()?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_JSP_PATH, "/WEB-INF/view/");
          ????}

          ????/**
          ?????* 獲取應(yīng)用靜態(tài)資源路徑
          ?????*/

          ????public?static?String getAppAssetPath()?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_ASSET_PATH, "/asset/");
          ????}

          ????/**
          ?????* 根據(jù)屬性名獲取 String 類型的屬性值
          ?????*/

          ????public?static?String getString(String key)?{
          ????????return?PropsUtil.getString(CONFIG_PROPS, key);
          ????}

          ????/**
          ?????* 根據(jù)屬性名獲取 int 類型的屬性值
          ?????*/

          ????public?static?int?getInt(String key)?{
          ????????return?PropsUtil.getInt(CONFIG_PROPS, key);
          ????}

          ????/**
          ?????* 根據(jù)屬性名獲取 boolean 類型的屬性值
          ?????*/

          ????public?static?boolean getBoolean(String key)?{
          ????????return?PropsUtil.getBoolean(CONFIG_PROPS, key);
          ????}
          }


          Class對象集合


          在完成了第一步加載配置文件之后, 我們接下來的第二步就是將應(yīng)用中所有的Class對象都存儲到一個集合中.


          (1) ClassUtil 工具類


          ClassUtil 工具類可以通過加載全限定類名得到Class類, 以及獲取指定包名下的所有Class類.


          public?final class?ClassUtil {

          ????private?static?final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);

          ????/**
          ?????* 獲取類加載器
          ?????*/

          ????public?static?ClassLoader getClassLoader() {
          ????????return?Thread.currentThread().getContextClassLoader();
          ????}

          ????/**
          ?????* 加載類
          ?????* @param className 類名
          ?????* @param isInitialized 是否初始化
          ?????* @return
          ?????*/

          ????public?static?Class loadClass(String?className, boolean?isInitialized) {
          ????????Class cls;
          ????????try?{
          ????????????cls = Class.forName(className, isInitialized, getClassLoader());
          ????????} catch?(ClassNotFoundException e) {
          ????????????LOGGER.error("load class failure", e);
          ????????????throw?new?RuntimeException(e);
          ????????}
          ????????return?cls;
          ????}

          ????/**
          ?????* 加載類(默認將初始化類)
          ?????*/

          ????public?static?Class loadClass(String?className) {
          ????????return?loadClass(className, true);
          ????}

          ????/**
          ?????* 獲取指定包名下的所有類
          ?????*/

          ????public?static?Set> getClassSet(String?packageName) {
          ????????Set> classSet = new?HashSet>();
          ????????try?{
          ????????????Enumeration urls = getClassLoader().getResources(packageName.replace(".", "/"));
          ????????????while?(urls.hasMoreElements()) {
          ????????????????URL url = urls.nextElement();
          ????????????????if?(url != null) {
          ????????????????????String?protocol = url.getProtocol();
          ????????????????????if?(protocol.equals("file")) {
          ????????????????????????String?packagePath = url.getPath().replaceAll("%20", " ");
          ????????????????????????addClass(classSet, packagePath, packageName);
          ????????????????????} else?if?(protocol.equals("jar")) {
          ????????????????????????JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
          ????????????????????????if?(jarURLConnection != null) {
          ????????????????????????????JarFile jarFile = jarURLConnection.getJarFile();
          ????????????????????????????if?(jarFile != null) {
          ????????????????????????????????Enumeration jarEntries = jarFile.entries();
          ????????????????????????????????while?(jarEntries.hasMoreElements()) {
          ????????????????????????????????????JarEntry jarEntry = jarEntries.nextElement();
          ????????????????????????????????????String?jarEntryName = jarEntry.getName();
          ????????????????????????????????????if?(jarEntryName.endsWith(".class")) {
          ????????????????????????????????????????String?className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
          ????????????????????????????????????????doAddClass(classSet, className);
          ????????????????????????????????????}
          ????????????????????????????????}
          ????????????????????????????}
          ????????????????????????}
          ????????????????????}
          ????????????????}
          ????????????}
          ????????} catch?(Exception e) {
          ????????????LOGGER.error("get class set failure", e);
          ????????????throw?new?RuntimeException(e);
          ????????}
          ????????return?classSet;
          ????}

          ????private?static?void?addClass(Set> classSet, String?packagePath, String?packageName) {
          ????????File[] files = new?File(packagePath).listFiles(new?FileFilter() {
          ????????????public?boolean?accept(File file) {
          ????????????????return?(file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
          ????????????}
          ????????});
          ????????for?(File file : files) {
          ????????????String?fileName = file.getName();
          ????????????if?(file.isFile()) {
          ????????????????String?className = fileName.substring(0, fileName.lastIndexOf("."));
          ????????????????if?(StringUtils.isNotEmpty(packageName)) {
          ????????????????????className = packageName + "."?+ className;
          ????????????????}
          ????????????????doAddClass(classSet, className);
          ????????????} else?{
          ????????????????String?subPackagePath = fileName;
          ????????????????if?(StringUtils.isNotEmpty(packagePath)) {
          ????????????????????subPackagePath = packagePath + "/"?+ subPackagePath;
          ????????????????}
          ????????????????String?subPackageName = fileName;
          ????????????????if?(StringUtils.isNotEmpty(packageName)) {
          ????????????????????subPackageName = packageName + "."?+ subPackageName;
          ????????????????}
          ????????????????addClass(classSet, subPackagePath, subPackageName);
          ????????????}
          ????????}
          ????}

          ????private?static?void?doAddClass(Set> classSet, String?className) {
          ????????Class cls = loadClass(className, false);
          ????????classSet.add(cls);
          ????}
          }


          (2) ClassHelper 助手類


          借助 ClassUtil 來實現(xiàn) ClassHelper 助手類, 這個類的功能很重要, 大家需要仔細看一下. ClassHelper 助手類在自身被加載的時候通過 ConfigHelper 助手類獲取應(yīng)用的基礎(chǔ)包名, 然后通過 ClassUtil 工具類來獲取基礎(chǔ)包名下所有類, 存儲到 CLASS_SET 集合中. 除此之外, 其他的方法在后面的代碼中會經(jīng)常被使用到.


          public?final class?ClassHelper?{

          ????/**
          ?????* 定義類集合(存放基礎(chǔ)包名下的所有類)
          ?????*/

          ????private?static?final Set> CLASS_SET;

          ????static?{
          ????????//獲取基礎(chǔ)包名
          ????????String basePackage = ConfigHelper.getAppBasePackage();
          ????????//獲取基礎(chǔ)包名下所有類
          ????????CLASS_SET = ClassUtil.getClassSet(basePackage);
          ????}

          ????/**
          ?????* 獲取基礎(chǔ)包名下的所有類
          ?????*/

          ????public?static?Set> getClassSet() {
          ????????return?CLASS_SET;
          ????}

          ????/**
          ?????* 獲取基礎(chǔ)包名下所有 Service 類
          ?????*/

          ????public?static?Set> getServiceClassSet() {
          ????????Set> classSet = new?HashSet>();
          ????????for?(Class cls : CLASS_SET) {
          ????????????if?(cls.isAnnotationPresent(Service.class)) {
          ????????????????classSet.add(cls);
          ????????????}
          ????????}
          ????????return?classSet;
          ????}

          ????/**
          ?????* 獲取基礎(chǔ)包名下所有 Controller 類
          ?????*/

          ????public?static?Set> getControllerClassSet() {
          ????????Set> classSet = new?HashSet>();
          ????????for?(Class cls : CLASS_SET) {
          ????????????if?(cls.isAnnotationPresent(Controller.class)) {
          ????????????????classSet.add(cls);
          ????????????}
          ????????}
          ????????return?classSet;
          ????}

          ????/**
          ?????* 獲取基礎(chǔ)包名下所有 Bean 類(包括:Controller、Service)
          ?????*/

          ????public?static?Set> getBeanClassSet() {
          ????????Set> beanClassSet = new?HashSet>();
          ????????beanClassSet.addAll(getServiceClassSet());
          ????????beanClassSet.addAll(getControllerClassSet());
          ????????return?beanClassSet;
          ????}

          ????/**
          ?????* 獲取基礎(chǔ)包名下某父類的所有子類 或某接口的所有實現(xiàn)類
          ?????*/

          ????public?static?Set> getClassSetBySuper(Class superClass) {
          ????????Set> classSet = new?HashSet>();
          ????????for?(Class cls : CLASS_SET) {
          ????????????//isAssignableFrom() 指 superClass 和 cls 是否相同或 superClass 是否是 cls 的父類/接口
          ????????????if?(superClass.isAssignableFrom(cls) && !superClass.equals(cls)) {
          ????????????????classSet.add(cls);
          ????????????}
          ????????}
          ????????return?classSet;
          ????}

          ????/**
          ?????* 獲取基礎(chǔ)包名下帶有某注解的所有類
          ?????*/

          ????public?static?Set> getClassSetByAnnotation(Class annotationClass) {
          ????????Set> classSet = new?HashSet>();
          ????????for?(Class cls : CLASS_SET) {
          ????????????if?(cls.isAnnotationPresent(annotationClass)) {
          ????????????????classSet.add(cls);
          ????????????}
          ????????}
          ????????return?classSet;
          ????}
          }


          Bean容器


          在將應(yīng)用中所有的Class對象都存儲到 CLASS_SET 集合中之后, 我們就可以來構(gòu)建Bean容器了.


          (1) ReflectionUtil 工具類


          我們需要一個反射工具類, 進行各種反射操作.


          public?final class?ReflectionUtil {

          ????private?static?final Logger LOGGER = LoggerFactory.getLogger(ReflectionUtil.class);

          ????/**
          ?????* 創(chuàng)建實例
          ?????*/

          ????public?static?Object?newInstance(Class cls) {
          ????????Object?instance;
          ????????try?{
          ????????????instance = cls.newInstance();
          ????????} catch?(Exception e) {
          ????????????LOGGER.error("new instance failure", e);
          ????????????throw?new?RuntimeException(e);
          ????????}
          ????????return?instance;
          ????}

          ????/**
          ?????* 創(chuàng)建實例(根據(jù)類名)
          ?????*/

          ????public?static?Object?newInstance(String?className) {
          ????????Class cls = ClassUtil.loadClass(className);
          ????????return?newInstance(cls);
          ????}

          ????/**
          ?????* 調(diào)用方法
          ?????*/

          ????public?static?Object?invokeMethod(Object?obj, Method method, Object... args) {
          ????????Object?result;
          ????????try?{
          ????????????method.setAccessible(true);
          ????????????result = method.invoke(obj, args);
          ????????} catch?(Exception e) {
          ????????????LOGGER.error("invoke method failure", e);
          ????????????throw?new?RuntimeException(e);
          ????????}
          ????????return?result;
          ????}

          ????/**
          ?????* 設(shè)置成員變量的值
          ?????*/

          ????public?static?void?setField(Object?obj, Field field, Object?value) {
          ????????try?{
          ????????????field.setAccessible(true); //去除私有權(quán)限
          ????????????field.set(obj, value);
          ????????} catch?(Exception e) {
          ????????????LOGGER.error("set field failure", e);
          ????????????throw?new?RuntimeException(e);
          ????????}
          ????}
          }


          (2) Bean容器助手類


          BeanHelper 在類加載時就會創(chuàng)建一個Bean容器 BEAN_MAP, 然后獲取到應(yīng)用中所有bean的Class對象, 再通過反射創(chuàng)建bean實例, 儲存到 BEAN_MAP 中.


          public?final class?BeanHelper {

          ????/**
          ?????* BEAN_MAP相當于一個Spring容器, 擁有應(yīng)用所有bean的實例
          ?????*/

          ????private?static?final Map, Object> BEAN_MAP = new?HashMap, Object>();

          ????static?{
          ????????//獲取應(yīng)用中的所有bean
          ????????Set> beanClassSet = ClassHelper.getBeanClassSet();
          ????????//將bean實例化, 并放入bean容器中
          ????????for?(Class beanClass : beanClassSet) {
          ????????????Object?obj = ReflectionUtil.newInstance(beanClass);
          ????????????BEAN_MAP.put(beanClass, obj);
          ????????}
          ????}

          ????/**
          ?????* 獲取 Bean 容器
          ?????*/

          ????public?static?Map, Object> getBeanMap() {
          ????????return?BEAN_MAP;
          ????}

          ????/**
          ?????* 獲取 Bean 實例
          ?????*/

          ????@SuppressWarnings("unchecked")
          ????public?static? T getBean(Class cls) {
          ????????if?(!BEAN_MAP.containsKey(cls)) {
          ????????????throw?new?RuntimeException("can not get bean by class: "?+ cls);
          ????????}
          ????????return?(T) BEAN_MAP.get(cls);
          ????}

          ????/**
          ?????* 設(shè)置 Bean 實例
          ?????*/

          ????public?static?void?setBean(Class cls, Object?obj) {
          ????????BEAN_MAP.put(cls, obj);
          ????}
          }


          實現(xiàn) IOC 功能


          最后就是實現(xiàn) IOC 了, 我們需要做的就是遍歷Bean容器中的所有bean, 為所有帶 @Autowired 注解的屬性注入實例. 這個實例從Bean容器中獲取.


          public final class?IocHelper?{

          ????/**
          ?????* 遍歷bean容器所有bean的屬性, 為所有帶@Autowired注解的屬性注入實例
          ?????*/

          ????static?{
          ????????//遍歷bean容器里的所有bean
          ????????Map, Object> beanMap = BeanHelper.getBeanMap();
          ????????if?(MapUtils.isNotEmpty(beanMap)) {
          ????????????for?(Map.Entry, Object> beanEntry : beanMap.entrySet()) {
          ????????????????//bean的class類
          ????????????????Class beanClass = beanEntry.getKey();
          ????????????????//bean的實例
          ????????????????Object?beanInstance = beanEntry.getValue();
          ????????????????//暴力反射獲取屬性
          ????????????????Field[] beanFields = beanClass.getDeclaredFields();
          ????????????????//遍歷bean的屬性
          ????????????????if?(ArrayUtils.isNotEmpty(beanFields)) {
          ????????????????????for?(Field beanField : beanFields) {
          ????????????????????????//判斷屬性是否帶Autowired注解
          ????????????????????????if?(beanField.isAnnotationPresent(Autowired.class)) {
          ????????????????????????????//屬性類型
          ????????????????????????????Class beanFieldClass = beanField.getType();
          ????????????????????????????//如果beanFieldClass是接口, 就獲取接口對應(yīng)的實現(xiàn)類
          ????????????????????????????beanFieldClass = findImplementClass(beanFieldClass);
          ????????????????????????????//獲取Class類對應(yīng)的實例
          ????????????????????????????Object?beanFieldInstance = beanMap.get(beanFieldClass);
          ????????????????????????????if?(beanFieldInstance != null) {
          ????????????????????????????????ReflectionUtil.setField(beanInstance, beanField, beanFieldInstance);
          ????????????????????????????}
          ????????????????????????}
          ????????????????????}
          ????????????????}
          ????????????}
          ????????}
          ????}

          ????/**
          ?????* 獲取接口對應(yīng)的實現(xiàn)類
          ?????*/

          ????public static?Class findImplementClass(Class interfaceClass) {
          ????????Class implementClass = interfaceClass;
          ????????//接口對應(yīng)的所有實現(xiàn)類
          ????????Set> classSetBySuper = ClassHelper.getClassSetBySuper(interfaceClass);
          ????????if?(CollectionUtils.isNotEmpty(classSetBySuper)) {
          ????????????//獲取第一個實現(xiàn)類
          ????????????implementClass = classSetBySuper.iterator().next();
          ????????}
          ????????return?implementClass;
          ????}
          }

          以上就是Bean容器和IOC功能的全部內(nèi)容, 當應(yīng)用啟動后, 就會生成Bean容器, 并實現(xiàn)IOC功能, 所有那些加了 @Autowired 注解的屬性, 別看他們在代碼中只是一個聲明, 其實在應(yīng)用啟動后他們都有實例啦!


          原文鏈接:blog.csdn.net/litianxiang_kaola/article/details/86647022



          瀏覽 20
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  A级免费电影 | 成人黄色视频网站免费观看 | 影音先锋一区二区三区视频特色 | 婷婷五月天激情丁香 | 大香蕉伊人乱伦 |