电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

使用Java反射模擬實現Spring的IoC容器的操作

瀏覽:57日期:2023-12-03 17:18:49
目錄實現的功能:項目結構下面是程序的項目結構圖:自定義注解容器實現測試實體類User的定義:實現的功能: 默認情況下將掃描整個項目的文件 可以使用@ComponentScan注解配置掃描路徑 只將被@Component注解修飾的類裝載到容器中 可以使用@AutoWired注解實現自動裝配 讀取配置文件中的聲明的類并注冊到容器中項目結構下面是程序的項目結構圖:

使用Java反射模擬實現Spring的IoC容器的操作

自定義注解

下面是自定義的三個注解: @AutoWired,@Component,@ComponentScan。

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface AutoWired {}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Component {}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface ComponentScan { String[] value();}容器實現

其中AnnotationConfigApplicationContext和ClassPathXMLApplicationContext為核心的類,其中

AnnotationConfigApplicationContext類實現掃描文件和解析注解等功能。

package learn.reflection.reflect;import learn.reflection.Bootstrap;import learn.reflection.annotation.AutoWired;import learn.reflection.annotation.Component;import learn.reflection.annotation.ComponentScan;import java.io.File;import java.io.InputStream;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;import java.util.Properties;import java.util.Set;public class AnnotationConfigApplicationContext<T>{ //使用HaspMap存儲Bean private HashMap<Class,Object> beanFactory=new HashMap<>(); //獲取Bean的方法 public T getBean(Class clazz){ return (T) beanFactory.get(clazz); } String path;//編譯后的字節碼存儲路徑 /** * 初始化ApplicationContext,加載注解修飾的Bean到beanFactory */ public void initContextByAnnotation(){ //編譯后的項目根目錄:D:/idea_workplace/javaAppliTechnology/target/classes/ path = AnnotationConfigApplicationContext.class.getClassLoader().getResource('').getFile(); //查看啟動類Bootstrap是否有定義掃描包 ComponentScan annotation = Bootstrap.class.getAnnotation(ComponentScan.class); if (annotation!=null){ //有定義就只掃描自定義的 String[] definedPaths = annotation.value(); if (definedPaths!=null&&definedPaths.length>0){loadClassInDefinedDir(path,definedPaths); } }else{ //默認掃描整個項目的目錄 System.out.println(path); findClassFile(new File(path)); } assembleObject(); } /** * 給@AutoWired修飾的屬性賦值 */ private void assembleObject(){ Set<Map.Entry<Class, Object>> entries = beanFactory.entrySet(); //掃描所有容器中的Bean for (Map.Entry<Class, Object> entry : entries) { Object value = entry.getValue(); //獲取所有屬性 Field[] fields = value.getClass().getDeclaredFields(); for (Field field : fields) {//如果被@AutoWired注解修飾則進行賦值AutoWired annotation = field.getAnnotation(AutoWired.class);if (annotation!=null){ try { field.setAccessible(true); field.set(value,beanFactory.get(field.getType())); } catch (IllegalAccessException e) { e.printStackTrace(); }} } } } /** * 掃描用戶自定義的包 * @param path * @param definedPaths */ private void loadClassInDefinedDir(String path, String[] definedPaths){ for (String definedPath : definedPaths) { //轉換成絕對路徑 String s = definedPath.replaceAll('.', '/'); String fullName=path+s; System.out.println(s); findClassFile(new File(fullName)); } } /** * 掃描項目中的每一個文件夾找到所有的class文件 */ private void findClassFile(File pathParent) { //路徑是否是目錄,子目錄是否為空 if (pathParent.isDirectory()) { File[] childrenFiles = pathParent.listFiles(); if (childrenFiles == null || childrenFiles.length == 0) {return; } for (File childrenFile : childrenFiles) {if (childrenFile.isDirectory()) { //遞歸調用直到找到所有的文件 findClassFile(childrenFile);} else { //找到文件 loadClassWithAnnotation(childrenFile);} } } } /** * 裝配找到的所有帶有@Component注解的類到容器 */ private void loadClassWithAnnotation(File file) { //1.去掉前面的項目絕對路徑 String pathWithClass=file.getAbsolutePath().substring(path.length()-1); //2.將路徑的“/”轉化為“.”和去掉后面的.class if (pathWithClass.contains('.class')){ String fullName = pathWithClass.replaceAll('', '.').replace('.class', ''); /** * 根據獲取到的類的全限定名使用反射將實例添加到beanFactory中 */ try {Class<?> clazz = Class.forName(fullName);//3.判斷是不是接口,不是接口才創建實例if (!clazz.isInterface()){ //4.是否具有@Bean注解 Component annotation = clazz.getAnnotation(Component.class); if (annotation!=null){ //5.創建實例對象 Object instance = clazz.newInstance(); //6.判斷是否有實現的接口 Class<?>[] interfaces = clazz.getInterfaces(); if (interfaces!=null&&interfaces.length>0){ //如果是有接口就將其接口的class作為key,實例對象作為value System.out.println('正在加載【'+interfaces[0].getName()+'】 實例對象:'+instance.getClass().getName()); beanFactory.put(interfaces[0],instance); }else{ System.out.println('正在加載【'+clazz.getName()+'】 實例對象:'+instance.getClass().getName()); beanFactory.put(clazz,instance); } //如果沒有接口就將自己的class作為key,實例對象作為value }} } catch (Exception e) {e.printStackTrace(); } } }}

ClassPathXMLApplicationContext類實現解析xml配置文件,并裝載組件到容器中。

package learn.reflection.reflect;import java.net.URL;import java.util.HashMap;import java.util.Map;import org.jdom2.Document;import org.jdom2.JDOMException;import org.jdom2.Element;import org.jdom2.xpath.XPath;import org.jdom2.input.SAXBuilder;import java.io.File;import java.io.IOException;import java.net.URL;import java.net.URISyntaxException;import java.util.*;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.InvocationTargetException;/** * @author Hai * @date 2020/5/17 - 18:47 */public class ClassPathXMLApplicationContext{ private File file; private Map<String,Object> map = new HashMap(); public ClassPathXMLApplicationContext(String config_file) { URL url = this.getClass().getClassLoader().getResource(config_file); try { file = new File(url.toURI()); XMLParsing(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void XMLParsing() throws Exception { SAXBuilder builder = new SAXBuilder(); Document document = builder.build(file); Element root = document.getRootElement(); List elementList = root.getChildren('bean'); Iterator i = elementList.iterator(); //讀取bean節點的所有信息 while (i.hasNext()) { Element bean = (Element) i.next(); String id = bean.getAttributeValue('id'); //根據class創建實例 String cls = bean.getAttributeValue('class'); Object obj = Class.forName(cls).newInstance(); Method[] method = obj.getClass().getDeclaredMethods(); List<Element> list = bean.getChildren('property'); for (Element el : list) {for (int n = 0; n < method.length; n++) { String name = method[n].getName(); String temp = null; //找到屬性對應的setter方法進行賦值 if (name.startsWith('set')) { temp = name.substring(3, name.length()).toLowerCase(); if (el.getAttribute('name') != null) { if (temp.equals(el.getAttribute('name').getValue())) {method[n].invoke(obj, el.getAttribute('value').getValue()); } } }} } map.put(id, obj); } } public Object getBean(String name) { return map.get(name); }}測試實體類User的定義:

@Componentpublic class User { private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; } public User() { } //省略getter,setter方法 }

在UserServiceImpl類中添加@Component注解,并使用@AutoWired注解注入容器中的IUerDao接口的實現類UserDaoImpl。

@Componentpublic class UserServiceImpl implements IUserService { @AutoWired private IUserDao userDao; @Override public void login(User user) { System.out.println('調用UserDaoImpl的login方法'); userDao.loginByUsername(user); }}

UserDaoImpl類同樣添加@Component注解

@Componentpublic class UserDaoImpl implements IUserDao { @Override public void loginByUsername(User user) { System.out.println('驗證用戶【'+user.getUsername()+'】登錄'); }}

在beans.xml中配置注冊User類,文件beans.xml的內容如下:

<?xml version='1.0' encoding='UTF-8'?><beans> <bean class='learn.reflection.entity.User'><property name='username' value='張三' /><property name='password' value='123' /> </bean></beans>

下面同時使用 AnnotationConfigApplicationContext類和 ClassPathXMLApplicationContext類。

Bootstrap類作為啟動類添加注解@ComponentScan,指定掃描learn.reflection.dao和learn.reflection.service這兩個包。

@ComponentScan(value = {'learn.reflection.dao','learn.reflection.service'})public class Bootstrap { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); applicationContext.initContextByAnnotation(); UserServiceImpl userService = (UserServiceImpl) applicationContext.getBean(IUserService.class); ClassPathXMLApplicationContext xmlApplicationContext = new ClassPathXMLApplicationContext('beans.xml'); User user = (User) xmlApplicationContext.getBean('user'); System.out.println(user); userService.login(user); }}

運行Bootstrap類,程序運行結果如下:

learn/reflection/dao正在加載【learn.reflection.dao.IUserDao】 實例對象:learn.reflection.dao.impl.UserDaoImpllearn/reflection/service正在加載【learn.reflection.service.IUserService】 實例對象:learn.reflection.service.impl.UserServiceImplUser{username=’張三’, password=’123’}調用UserDaoImpl的login方法驗證用戶【張三】登錄

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
主站蜘蛛池模板: 湖南成人高考报名-湖南成考网| 污水处理设备维修_污水处理工程改造_机械格栅_过滤设备_气浮设备_刮吸泥机_污泥浓缩罐_污水处理设备_污水处理工程-北京龙泉新禹科技有限公司 | 【直乐】河北石家庄脊柱侧弯医院_治疗椎间盘突出哪家医院好_骨科脊柱外科专业医院_治疗抽动症/关节病骨伤权威医院|排行-直乐矫形中医医院 | 信阳网站建设专家-信阳时代网联-【信阳网站建设百度推广优质服务提供商】信阳网站建设|信阳网络公司|信阳网络营销推广 | 河南砖机首页-全自动液压免烧砖机,小型砌块水泥砖机厂家[十年老厂] | 小威小说网 - 新小威小说网 - 小威小说网小说搜索引擎 | 除甲醛公司-甲醛检测治理-杭州创绿家环保科技有限公司-室内空气净化十大品牌 | 全自动贴标机-套标机-工业热风机-不干胶贴标机-上海厚冉机械 | 兰州牛肉面加盟,兰州牛肉拉面加盟-京穆兰牛肉面 | 手持式3d激光扫描仪-便携式三维立体扫描仪-北京福禄克斯 | 六自由度平台_六自由度运动平台_三自由度摇摆台—南京全控科技 | 阁楼货架_阁楼平台_仓库仓储设备_重型货架_广州金铁牛货架厂 | 带式压滤机_污泥压滤机_污泥脱水机_带式过滤机_带式压滤机厂家-河南恒磊环保设备有限公司 | 交通信号灯生产厂家_红绿灯厂家_电子警察监控杆_标志杆厂家-沃霖电子科技 | 商标转让-商标注册-商标查询-软著专利服务平台 - 赣江万网 | 走心机厂家,数控走心机-台州博城智能科技有限公司 | 活性氧化铝球|氧化铝干燥剂|分子筛干燥剂|氢氧化铝粉-淄博同心材料有限公司 | 集装袋吨袋生产厂家-噸袋廠傢-塑料编织袋-纸塑复合袋-二手吨袋-太空袋-曹县建烨包装 | 胜为光纤光缆_光纤跳线_单模尾纤_光纤收发器_ODF光纤配线架厂家直销_北京睿创胜为科技有限公司 - 北京睿创胜为科技有限公司 | LED太阳能中国结|发光红灯笼|灯杆造型灯|节日灯|太阳能灯笼|LED路灯杆装饰造型灯-北京中海轩光电 | 上海璟文空运首页_一级航空货运代理公司_机场快递当日达 | 冷藏车-东风吸污车-纯电动环卫车-污水净化车-应急特勤保障车-程力专汽厂家-程力专用汽车股份有限公司销售二十一分公司 | 骁龙云呼电销防封号系统-axb电销平台-外呼稳定『免费试用』 | 压力控制器,差压控制器,温度控制器,防爆压力控制器,防爆温度控制器,防爆差压控制器-常州天利智能控制股份有限公司 | 钢衬四氟管道_钢衬四氟直管_聚四氟乙烯衬里管件_聚四氟乙烯衬里管道-沧州汇霖管道科技有限公司 | 药品仓库用除湿机-变电站用防爆空调-油漆房用防爆空调-杭州特奥环保科技有限公司 | 层流手术室净化装修-检验科ICU改造施工-华锐净化工程-特殊科室建设厂家 | 仿古建筑设计-仿古建筑施工-仿古建筑公司-汉匠古建筑设计院 | 防渗土工膜|污水处理防渗膜|垃圾填埋场防渗膜-泰安佳路通工程材料有限公司 | 矿用履带式平板车|探水钻机|气动架柱式钻机|架柱式液压回转钻机|履带式钻机-启睿探水钻机厂家 | 旗杆生产厂家_不锈钢锥形旗杆价格_铝合金电动旗杆-上海锥升金属科技有限公司 | 宁波普瑞思邻苯二甲酸盐检测仪,ROHS2.0检测设备,ROHS2.0测试仪厂家 | 京港视通报道-质量走进大江南北-京港视通传媒[北京]有限公司 | 淄博不锈钢,淄博不锈钢管,淄博不锈钢板-山东振远合金科技有限公司 | 产业规划_产业园区规划-产业投资选址及规划招商托管一体化服务商-中机院产业园区规划网 | 防水套管厂家_刚性防水套管_柔性防水套管_不锈钢防水套管-郑州中泰管道 | 校服厂家,英伦校服定做工厂,园服生产定制厂商-东莞市艾咪天使校服 | 杭州中策电线|中策电缆|中策电线|杭州中策电缆|杭州中策电缆永通集团有限公司 | 臭氧灭菌箱-油桶加热箱-原料桶加热融化烘箱-南京腾阳干燥设备厂 臭氧发生器_臭氧消毒机 - 【同林品牌 实力厂家】 | 伶俐嫂培训学校_月嫂培训班在哪里报名学费是多少_月嫂免费政府培训中心推荐 | 河北中仪伟创试验仪器有限公司是专业生产沥青,土工,水泥,混凝土等试验仪器的厂家,咨询电话:13373070969 |