首页 > 其他分享 >Spring —— IOC

Spring —— IOC

时间:2023-06-18 10:22:43浏览次数:48  
标签:xml 对象 Spring bean new IOC Class 属性

Spring — IOC

  • 传统方式:先前 service 层调用 dao 实现类:常用 new 方式,高耦合 ( 即依赖 —— 模块与模块之间的联系 )

    • 而好的程序应该是:高内聚 ( 模块内部功能的联系 ) 低耦合
  • New 的方式就是写死了,是硬编码 ( 一般来说应该是要避免的 ) 要改变的话就是改源代码

  • 将紧耦合变为松耦合,松耦合尽量做到不耦合

    • 采用反射方式解耦

    • 例:旧方法是需要在参数列表内传入一个 new 的对象,而采用反射思想的话就是直接传入一个字符串,而且字符串可以通过控制台输入

      // F1:
      Scanner sc = new Scanner(System.in);
      String str = sc.nextLine(); //读取,之后用 str.equals() 根据控制台情况来具体 new 等操作
      
      // F2:
      Class cls = Class.forName(str); // 填入字符串(类的全包名),用一个Class 类型来接收
      cls.newInstance(); // 完成创建:一个控制台输入包的 java 类对象
      
    • 输入字符串,创建了对象 ——> 反射

  • 反射是框架设计的灵魂,是在程序运行过程中:

    • 对任意一个类,都能够 [ 知道 ] 它的所有属性和方法

    • 对任意一个对象,都能够 [ 调用 ] 它的所有属性和方法

    • 这种动态获取信息以及动态创建对象的功能称为 Java 的反射机制

  • Spring 实现解耦的两项技术:

    1. 反射

    2. 读配置文件

  • Class 对象 ( 类模板,类的模板对象 ) 的获取方式:

    • 对象.getClass() 方法

    • 类.class属性

    • Class.forName(String className) —— 推荐方法

    • 注意:三个方式都是获取的同一个对象,只会执行一次构造方法,即一个类在虚拟机中只能有一个模板对象

    • 例:

      cls.newInstance("A包名");
      A a2 = (A)cls.newInstance(); // 找到模板后,就可以创建对象了
      
    • class 文件:字节码文件。加载到内存就会生成一个类模板对象,就可以在代码 new 的时候复制粘贴来用了

  • 反射缺点:效率要低,没直接创建来的快

  • 了解:spring 官网下载 spring 是一个压缩包,内 libs 里有 class 的 jar 包、解释 API 文档 javadoc、源码源文件 sources ( 三为一体 ),用得着的话就只拷贝 jar 包就好 —— 早期方法,现都用 maven 方法更便利

第一个 Spring 编码

  • 四个基础包 spring-core、beans、context、expression ( 版本要一致 ) 还有 commons-logging 日志基础包,依赖导入时会自动导入 ( Spring 框架依赖于此组件 Apache Commons Logging ),只导 context 也可 ( 其他四个都会自行导入 )

  • xml:

    <bean id = "不能重" class = "全包名...X" ></bean>  //还可能有 scope 属性表示作用范围,singleton 单例(默认),prototype 是多例,每次使用都会创建对象
    
  • Test.java:

    // psvm
    ApplicationContext ctx = new ClassPathXmlApplicationContext("1.xml"); // 创建一个大的容器类,ApplicationContext 是个接口,后为实现类,就会到配置文件中把 bean 创建出来
    X x = ctx.getBean("bean的id", 类模板—X.class) // 其实就很像A a2 = (A)cls.newInstance();
    // x.方法调用(X可以是一个类 / 实现类)
    

Bean对象的生命周期:

  • bean标签的 init-method 属性设置初始化方法
  • bean标签的 destroy-method 属性设置销毁方法
  • 单例对象的生命周期:容器加载 / 创建时对象便出生,直到容器销毁才死亡,即容器存在对象就一直活着
  • 多利对象的生命周期:什么时候用,就什么时候创建 ( 每次使用都会创建 ),对象在使用过程中就会一直活着,死亡交给java垃圾回收机制处理 ( 太多 spring 搞不定 )

IOC 底层原理

  • ioc:控制反转,把对象的创建调用交由 spring 管理,使用目的 —— 降低耦合度

  • ioc 过程:xml 中配 bean <......>,使用工厂类 ( 其实就是容器 ) ApplicationContext = ......,做反射... = ...getBean(...)

  • Spring 提供 IOC 容器实现的两种方式:

    • BeanFactory

      BeanFactory xx = new XmlBeanFactory(new ClassPathResource("1.xml")) // 工厂模式
      xx.getBean // 用的少,原始方式 
      
    • ApplicationContext —— 是子类,功能更强大,用的更多

      其接口有两个实现类

      • ClassPathXmlApplicationContext("Name") 用的多:Name 路径:就是 java 或 resource 下的文件名,如:1.xml
      • FileSystemXmlApplicationContext("文件路径"):文件路径: D:\idea\Workspace.....

Spring IOC 配置 Bean 的两种方式

  • 依赖注入 DI ( Dependency Injection ) 是 ioc 的具体体现

  • Bean 的依赖注入值类型:

    • 字面值
    • 其他 Bean
    • 集合类
  • 基于 xml 文件的方式 —— 集中式的元数据,与源代码无绑定 ( Bean 的 id 不指定的话就默认为类名 )

    • 新建xml的话除了bean等,开头部分还需要加xmlns工作空间,xsi里的 http://...... 约束两个,一共改三处
  • Bean 的依赖关系通常有两种实现方式:

    • 构造器注入

      • bean 子标签 constructor-arg 里,属性 name、value:只能是基本数据类型 + String ( 除开 String 的引用数据类型不能写入 ) —— 似表单
      • 其中 name:注入参数在构造函数中的名称。ref:其他 bean 的 id。value:注入的数据值。在 bean 标签里填写完值后,就可以在 Test 测试时 getBean 后直接输出一串对象值:内容就是 bean 里 value 所写
    • 属性 setter 注入

      • 属性注入 ( 推荐 ) 用的最多 —— 即把要用的对象当作属性来看,什么时候要什么时候就给你用

        属性注入:service 的 bean 子标签 property:name 为所取的属性名 ( != 变量 ),ref 为引用的 daoimpl 的 id

    • 注意:

      • 因为常如以下所用,所用就慢慢默认变量为属性了,实则不是

      img

      • name 前提是在 service 所需类里加上 daoimpl 的 getter and setter 方法 ( 方法是针对属性的,而属性就是 bean 里的子标签的 name ),service 里非 new 写的 UserDaoImpl dao 只是一变量,而 xml 里的 name 属性指的是 getXxx 和 setXxx 后面的首字母小写的 xxx ( 但在此处大写也可以 )
      • 若是 bean 的 dao 想更换,那就可以直接在 dao 层增加,虽是更改了源码,但实际上新增 dao 可以由别人写,自己只接受其 class 字节码文件即可 ( 跨平台特点 ),不需要编译,可以直接用 ———— bean更方便,解耦
  • 基于注解的方式 —— 分散式的元数据,与源代码紧绑定

    • 在四个 jar 包基础上再加上 aop 依赖包

    • 不配置 bean 还想创建出来,就得加一个扫描到包的 context 标签:

      <context:component-scan base-package="com.qut" ></context:component-scan>
      
    • 在 serviceimpl 开头加上 ( 即作用到类上 ) @Component(value = “xxxx”) ———— 作用就相当于在 spring 的配置 xml 中写一个 bean 标签

      • 没写 value 的话就是类名的首字母小写
    • @Controller ( 用控制器上 - 表现层 )、@Service ( 推荐到 Service 层 - 业务层 )、@Repository ( 推荐 Dao 层 - 持久层 ) —— 作用属性都相同,是 spring 为了提供更明确的语义

    • 注意:

      • @Autowired:主要用在只有唯一一个类型匹配,此时 public UserDao ud; 就可以删去 xml 方式时的 get 和 set ud 的方法了

      • @Qualifier 与 @Autowired 搭配使用:当一个 UserDao 有两个 Impl 实现类时,需要在 @Autowired 后再加上 @Qualifier(“xxxImpl”) 指定 service 层用哪个 Impl 实现类

      • @Resource 使用偏少

      • @Value 使用偏少

代码

//        通过控制台输入信息
        Scanner sc = new Scanner(System.in);
//        获取控制台输入字符
        String str = sc.nextLine();
//        Class可以看作一个模板,找到了str字符串对应模板
        Class cls1 = Class.forName(str); // ("com.qut.test.A")  -F1
//		  Class cls1 = a.getClass(); // A a = new A();  -F2
// 		  Class cls2 = A.class; // A a = new A();  -F3
// 		  完成创建
        cls1.newInstance();

//        配成一个大的容器ctx:含有1.xml内的信息
		ApplicationContext ctx = new ClassPathXmlApplicationContext("1.xml");
// 		  通过容器获取A实例 ——— 反射
		A a1 = ctx.getBean("mybean1",A.class);	 // 1.xml里一bean的id为:mybean1

标签:xml,对象,Spring,bean,new,IOC,Class,属性
From: https://www.cnblogs.com/zhu-ya-zhu/p/17488780.html

相关文章

  • SpringBoot中跨域问题的处理
    跨越问题产生原因:产生跨域问题的原因是浏览器的同源策略,所谓同源是指:域名,协议,端口相同。如果不同,将会出现跨域问题。一、创建项目我们创建两个项目,一个命名为provider提供服务,一个命名为consumer消费服务,第一个项目端口配置为8080,第二个项目端口配置为8081,然后在provider中提供一个......
  • SpringBoot整合RocketMQ
    前提是必须已经安装了RocketMQ并配置好相关的环境变量(自行百度) 第一步: 第二步: 第三步:  第四步: ......
  • 手写SpringBoot启动器主要步骤
    这里写目录标题背景过程2.1自启动实现原理2.2手动实现SpringBoot自启动2.2.1宏观2.2.1微观2.2.1.1三个服务之间调用2.2.1.2自定义注解2.2.1.1业务组装2.2.1.3启动类升华自定义注解:手动装配组件:简化启动过程:自动化注入依赖:简化启动类:背景更好的理解框架:通过手写SpringBoot启动类,......
  • springboot中自定义注解在service方法中,aop失效
    问题描述写了个自定义注解,但是该注解只会出现在serviece层中的方法中。启动发现aop未拦截到问题原因:调用service中的xx()方法时,Spring的动态代理帮我们动态生成了一个代理的对象,暂且叫他$XxxxService。所以调用xx()方法实际上是代理对象$XxxxService调用的。但是在xx()方法内调用同......
  • springboot注册过滤器
    springboot注册过滤器需要使用过滤器的话,优先选择拦截器。因为拦截器符合aop思想。在springboot中使用过滤器有三种方式。分别如下方式一:传统web在传统javaweb、ssm中使用过滤器差不多类似,这里以java配置为例,实现Filter接口@WebFilter("/*")publicclassMyFilter01i......
  • SpringBatch从入门到实战(一):简介和环境搭建
    一:简介SpringBatch是一个轻量级的批处理框架,适合处理大批量的数据(如百万级别)。功能就是从一个地方读数据写到另一个地方去。一般都是系统之间不能直接访问同一个数据库,需要通过文件来交换数据。二:从文件中读然后写到数据库这代码谁都会写,那么为什么还要使用框架?try(BufferedReader......
  • 【框架源码】Spring源码解析之Bean创建源码流程
    问题:Spring中是如何初始化单例bean的?我们都知道Spring解析xml文件描述成BeanDefinition,解析BeanDefinition最后创建Bean将Bean放入单例池中,那么Spring在创建Bean的这个过程都做了什么。Spring核心方法refresh()中最最重要的一个方法finishBeanFactoryInitialization()方法,该方法......
  • Spring框架中的线程池
    Spring框架中的线程池使用Java的ExecutorService接口实现ExecutorService是Java提供的用于管理线程池的高级工具。下面是在Spring框架中使用线程池的一般步骤:导入所需的依赖首先,确保你的项目中包含了使用线程池所需的依赖。通常情况下,你可以使用SpringBoot来创建项目,它会自动包含......
  • 2、spring
    1、简介springframework是其他spring框架的基础如springboot、springcloud2、Ioc  ......
  • SpringBoot整合ActiveMQ
    第一步: 第二步: 第三步: 下面如有需要才使用 ......