我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring6-IoC(Inversion of Control)控制反转和DI(Dependency Injection)依赖注入,手动实现IOC

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring6-IoC(Inversion of Control)控制反转和DI(Dependency Injection)依赖注入,手动实现IOC

文章目录

1、Java反射

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的 反射机制 。简单来说,反射机制指的是程序在运行时能够获取自身的信息

要想解剖一个类,必须先要获取到该类的Class对象。而剖析一个类或用反射解决具体的问题就是使用相关API (1)java.lang.Class(2)java.lang.reflect ,所以,Class对象是反射的根源

相关文章:

自定义类

package org.example.reflect;public class Car {    //属性    private String name;    private int age;    private String color;    //无参数构造    public Car() {    }    //有参数构造    public Car(String name, int age, String color) {        this.name = name;        this.age = age;        this.color = color;    }    //普通方法    private void run() {        System.out.println("私有方法-run.....");    }    //get和set方法    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getColor() {        return color;    }    public void setColor(String color) {        this.color = color;    }    @Override    public String toString() {        return "Car{" +                "name='" + name + '\'' +                ", age=" + age +                ", color='" + color + '\'' +                '}';    }}

编写测试类

package org.example.reflect;import org.junit.jupiter.api.Test;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class TestCar {    //1、获取Class对象多种方式    @Test    public void test01() throws Exception {        //1 类名.class        Class clazz1 = Car.class;        //2 对象.getClass()        Class clazz2 = new Car().getClass();        //3 Class.forName("全路径")        Class clazz3 = Class.forName("org.example.reflect.Car");        //实例化        Car car = (Car)clazz3.getConstructor().newInstance();        System.out.println(car);    }    //2、获取构造方法    @Test    public void test02() throws Exception {        Class clazz = Car.class;        //获取所有构造        // getConstructors()获取所有public的构造方法//        Constructor[] constructors = clazz.getConstructors();        // getDeclaredConstructors()获取所有的构造方法public  private        Constructor[] constructors = clazz.getDeclaredConstructors();        for (Constructor c:constructors) {            System.out.println("方法名称:"+c.getName()+" 参数个数:"+c.getParameterCount());        }        //指定有参数构造创建对象        //1 构造public//        Constructor c1 = clazz.getConstructor(String.class, int.class, String.class);//        Car car1 = (Car)c1.newInstance("夏利", 10, "红色");//        System.out.println(car1);                //2 构造private        Constructor c2 = clazz.getDeclaredConstructor(String.class, int.class, String.class);        c2.setAccessible(true);        Car car2 = (Car)c2.newInstance("捷达", 15, "白色");        System.out.println(car2);    }    //3、获取属性    @Test    public void test03() throws Exception {        Class clazz = Car.class;        Car car = (Car)clazz.getDeclaredConstructor().newInstance();        //获取所有public属性        //Field[] fields = clazz.getFields();        //获取所有属性(包含私有属性)        Field[] fields = clazz.getDeclaredFields();        for (Field field:fields) {            if(field.getName().equals("name")) {                //设置允许访问                field.setAccessible(true);                field.set(car,"五菱宏光");                System.out.println(car);            }            System.out.println(field.getName());        }    }    //4、获取方法    @Test    public void test04() throws Exception {        Car car = new Car("奔驰",10,"黑色");        Class clazz = car.getClass();        //1 public方法        Method[] methods = clazz.getMethods();        for (Method m1:methods) {            //System.out.println(m1.getName());            //执行方法 toString            if(m1.getName().equals("toString")) {                String invoke = (String)m1.invoke(car);                //System.out.println("toString执行了:"+invoke);            }        }        //2 private方法        Method[] methodsAll = clazz.getDeclaredMethods();        for (Method m:methodsAll) {            //执行方法 run            if(m.getName().equals("run")) {                m.setAccessible(true);                m.invoke(car);            }        }    }}

2、实现Spring的IOC

IoC(控制反转)和DI(依赖注入)是Spring里面核心的东西,如何实现Spring框架最核心的部分?

①搭建模块

搭建模块:ioc-spring

②准备测试需要的bean

添加依赖

<dependencies>        <dependency>        <groupId>org.junit.jupitergroupId>        <artifactId>junit-jupiter-apiartifactId>        <version>5.3.1version>    dependency>dependencies>

创建UserDao接口

package org.example.spring6.test.dao;public interface UserDao {    public void print();}

创建UserDaoImpl实现

package org.example.spring6.test.dao.impl;import org.example.spring.dao.UserDao;public class UserDaoImpl implements UserDao {    @Override    public void print() {        System.out.println("Dao层执行结束");    }}

创建UserService接口

package org.example.spring6.test.service;public interface UserService {    public void out();}

创建UserServiceImpl实现类

package org.example.spring.test.service.impl;import org.example.spring.core.annotation.Bean;import org.example.spring.service.UserService;@Beanpublic class UserServiceImpl implements UserService {//    private UserDao userDao;    @Override    public void out() {        //userDao.print();        System.out.println("Service层执行结束");    }}

③定义注解

通过注解的形式加载bean与实现依赖注入

bean注解

package org.example.spring.core.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Bean {}

依赖注入注解

package org.example.spring.core.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface Di {}

说明:上面两个注解可以随意取名

④定义bean容器接口

package org.example.spring.core;public interface ApplicationContext {    Object getBean(Class clazz);}

⑤编写注解bean容器接口实现

AnnotationApplicationContext基于注解扫描bean

package org.example.spring.core;import java.util.HashMap;public class AnnotationApplicationContext implements ApplicationContext {    //存储bean的容器    private HashMap<Class, Object> beanFactory = new HashMap<>();    @Override    public Object getBean(Class clazz) {        return beanFactory.get(clazz);    }        public AnnotationApplicationContext(String basePackage) {            }}

⑥编写扫描bean逻辑

通过构造方法传入包的base路径,扫描被@Bean(自己定义的)注解的java对象,完整代码如下:

package org.example.spring.core;import org.example.spring.core.annotation.Bean;import java.io.File;import java.util.HashMap;public class AnnotationApplicationContext implements ApplicationContext {    //存储bean的容器    private HashMap<Class, Object> beanFactory = new HashMap<>();    private static String rootPath;    @Override    public Object getBean(Class clazz) {        return beanFactory.get(clazz);    }        public AnnotationApplicationContext(String basePackage) {       try {            String packageDirName = basePackage.replaceAll("\\.", "\\\\");            Enumeration<URL> dirs =Thread.currentThread().getContextClassLoader().getResources(packageDirName);            while (dirs.hasMoreElements()) {                URL url = dirs.nextElement();                String filePath = URLDecoder.decode(url.getFile(),"utf-8");                rootPath = filePath.substring(0, filePath.length()-packageDirName.length());                loadBean(new File(filePath));            }        } catch (Exception e) {            throw new RuntimeException(e);        }    }    private  void loadBean(File fileParent) {        if (fileParent.isDirectory()) {            File[] childrenFiles = fileParent.listFiles();            if(childrenFiles == null || childrenFiles.length == 0){                return;            }            for (File child : childrenFiles) {                if (child.isDirectory()) {                    //如果是个文件夹就继续调用该方法,使用了递归                    loadBean(child);                } else {                    //通过文件路径转变成全类名,第一步把绝对路径部分去掉                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1);                    //选中class文件                    if (pathWithClass.contains(".class")) {                        //    com.xinzhi.dao.UserDao                        //去掉.class后缀,并且把 \ 替换成 .                        String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", "");                        try {Class<?> aClass = Class.forName(fullName);//把非接口的类实例化放在map中if(!aClass.isInterface()){    Bean annotation = aClass.getAnnotation(Bean.class);    if(annotation != null){        Object instance = aClass.newInstance();        //判断一下有没有接口        if(aClass.getInterfaces().length > 0) {            //如果有接口把接口的class当成key,实例对象当成value            System.out.println("正在加载【"+ aClass.getInterfaces()[0] +"】,实例对象是:" + instance.getClass().getName());            beanFactory.put(aClass.getInterfaces()[0], instance);        }else{            //如果有接口把自己的class当成key,实例对象当成value            System.out.println("正在加载【"+ aClass.getName() +"】,实例对象是:" + instance.getClass().getName());            beanFactory.put(aClass, instance);        }    }}                        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {e.printStackTrace();                        }                    }                }            }        }    }}

⑦java类标识Bean注解

@Beanpublic class UserServiceImpl implements UserService
@Beanpublic class UserDaoImpl implements UserDao 

⑧测试Bean加载

package org.example.spring;import org.example.spring.core.AnnotationApplicationContext;import org.example.spring.core.ApplicationContext;import org.example.spring.test.service.UserService;import org.junit.jupiter.api.Test;public class SpringIocTest {    @Test    public void testIoc() {        ApplicationContext applicationContext = new AnnotationApplicationContext("org.example.spring.test");        UserService userService = (UserService)applicationContext.getBean(UserService.class);        userService.out();        System.out.println("run success");    }}

控制台打印测试

⑨依赖注入

只要userDao.print();调用成功,说明就注入成功

package org.example.spring.test.service.impl;import org.example.spring.core.annotation.Bean;import org.example.spring.core.annotation.Di;import org.example.spring.dao.UserDao;import org.example.spring.service.UserService;@Beanpublic class UserServiceImpl implements UserService {    @Di    private UserDao userDao;    @Override    public void out() {        userDao.print();        System.out.println("Service层执行结束");    }}

执行第八步:报错了,说明当前userDao是个空对象,还没有进行注入

⑩依赖注入实现

package org.example.spring.core;import org.example.spring.core.annotation.Bean;import org.example.spring.core.annotation.Di;import java.io.File;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class AnnotationApplicationContext implements ApplicationContext {    //存储bean的容器    private HashMap<Class, Object> beanFactory = new HashMap<>();    private static String rootPath;    @Override    public Object getBean(Class clazz) {        return beanFactory.get(clazz);    }        public AnnotationApplicationContext(String basePackage) {        try {            String packageDirName = basePackage.replaceAll("\\.", "\\\\");            Enumeration<URL> dirs =Thread.currentThread().getContextClassLoader().getResources(packageDirName);            while (dirs.hasMoreElements()) {                URL url = dirs.nextElement();                String filePath = URLDecoder.decode(url.getFile(),"utf-8");                rootPath = filePath.substring(0, filePath.length()-packageDirName.length());                loadBean(new File(filePath));            }        } catch (Exception e) {            throw new RuntimeException(e);        }                //依赖注入        loadDi();    }        private  void loadBean(File fileParent) {        if (fileParent.isDirectory()) {            File[] childrenFiles = fileParent.listFiles();            if(childrenFiles == null || childrenFiles.length == 0){                return;            }            for (File child : childrenFiles) {                if (child.isDirectory()) {                    //如果是个文件夹就继续调用该方法,使用了递归                    loadBean(child);                } else {                    //通过文件路径转变成全类名,第一步把绝对路径部分去掉                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1);                    //选中class文件                    if (pathWithClass.contains(".class")) {                        //    com.xinzhi.dao.UserDao                        //去掉.class后缀,并且把 \ 替换成 .                        String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", "");                        try {Class<?> aClass = Class.forName(fullName);//把非接口的类实例化放在map中if(!aClass.isInterface()){    Bean annotation = aClass.getAnnotation(Bean.class);    if(annotation != null){        Object instance = aClass.newInstance();        //判断一下有没有接口        if(aClass.getInterfaces().length > 0) {            //如果有接口把接口的class当成key,实例对象当成value            System.out.println("正在加载【"+ aClass.getInterfaces()[0] +"】,实例对象是:" + instance.getClass().getName());            beanFactory.put(aClass.getInterfaces()[0], instance);        }else{            //如果有接口把自己的class当成key,实例对象当成value            System.out.println("正在加载【"+ aClass.getName() +"】,实例对象是:" + instance.getClass().getName());            beanFactory.put(aClass, instance);        }    }}                        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {e.printStackTrace();                        }                    }                }            }        }    }    private void loadDi() {        for(Map.Entry<Class,Object> entry : beanFactory.entrySet()){            //就是咱们放在容器的对象            Object obj = entry.getValue();            Class<?> aClass = obj.getClass();            Field[] declaredFields = aClass.getDeclaredFields();            for (Field field : declaredFields){                Di annotation = field.getAnnotation(Di.class);                if( annotation != null ){                    field.setAccessible(true);                    try {                        System.out.println("正在给【"+obj.getClass().getName()+"】属性【" + field.getName() + "】注入值【"+ beanFactory.get(field.getType()).getClass().getName() +"】");                        field.set(obj,beanFactory.get(field.getType()));                    } catch (IllegalAccessException e) {                        e.printStackTrace();                    }                }            }        }    }}

执行第八步:测试依赖注入,执行成功

来源地址:https://blog.csdn.net/weixin_43847283/article/details/131158742

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring6-IoC(Inversion of Control)控制反转和DI(Dependency Injection)依赖注入,手动实现IOC

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录