spring的IOC原理

作者:@kuaiquxie
作者的github:https://github.com/bitebita
本文为作者原创,如需转载,请注明出处:https://www.cnblogs.com/dzwj/p/16476074.html


控制反转(IOC)原型

之前,程序是主动创建对象!控制权在程序猿手上!

使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!

这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。

系统的耦合性大大降低~,可以更加专注的在业务的实现上!这是IOC的原型!

 

IOC本质 控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现loC的一种方法, 也有人认为Dl只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中, 对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体, Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。 在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,Dl)。

 

这个过程就叫控制反转: 控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的. 反转:程序本身不创建对象,而变成被动的接收对象.依赖注入:就是利用set方法来进行注入的. IOC是一种编程思想,由主动的编程变成被动的接收. 可以通过newClassPathXmlApplicationContext去浏览一下底层源码. OK,到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改, 所谓的IOC,一句话: 对象由 Spring 来创建,管理,装配!

 

beans.xml 基本代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

   <!--使用 Spring 来创建对象,在 Spring 这些都称为 Bean,对象就是Bean-->
   <!--
  id:bean 的唯一标识符,相当于学过的对象名
  class:bean 对象所对应的全限定名:包名+类名
  name: 也是别名,而且 name 可以同时取多个别名
   -->
   <bean id="" class="com.jing" name="">
   
   </bean>

</beans>

 

测试类: // 获取 Spring 的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

IOC创建对象: 默认使用无参构造创建对象 假设使用有参构造创建对象 1.下标赋值 2.类型(不常用) 3.参数名(常用) 在配置文件加载的时候,容器中管理的对象就已经初始化了

 

spring配置:

1.别名:

    <alias></alias>

2.Bean的配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

   <!--使用 Spring 来创建对象,在 Spring 这些都称为 Bean,对象就是Bean-->
   <!--
  id: bean 的唯一标识符,相当于学过的对象名
  class: bean 对象所对应的全限定名:包名+类名
  name: 也是别名,而且 name 可以同时取多个别名
   -->
   <!--property 属性,财产 property里的name属性,来自set方法,尽量不变-->
   <bean id="" class="com.jing" name="">
   
   </bean>

</beans>


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

   <!--使用 Spring 来创建对象,在 Spring 这些都称为 Bean,对象就是Bean-->
   <bean id="" class="com.jing" name="">
   
   </bean>

</beans>

3.import: import 一般用于团队开发使用,可以将多个配置文件,导入合并为一个 代码:

    <import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>

 

标签自闭合: <p/>

 

依赖注入:

1.构造器注入 2.set方式注入(重点) 3.拓展方式注入

set方式注入:

完善注入信息:

<bean id="address" class="com.jing.pojo.Address">
   <property name="address" value="北京"/>
</bean>

<bean id="student" class="com.jing.pojo.Student" name="">
   <!--1. 普通值注入,value-->
   <property name="name" value="小明"/>
   <!--2. Bean 注入,ref:引用 bean 中的 id-->
   <property name="address" ref="address"/>
   <!--3. 数组注入,ref-->
   <property name="books">
       <array>
           <value>红楼梦</value>
           <value>西游记</value>
           <value>水浒传</value>
           <value>三国演义</value>
       </array>
   </property>
   <!--4. list-->
   <property name="hobbys">
       <list>
           <value>听歌</value>
           <value>写作业</value>
           <value>玩游戏</value>
       </list>
   </property>
   <!--5. Map-->
   <property name="card">
       <map>
           <entry key="身份证" value="123"/>
       </map>
   </property>
   <!--6. Set-->
   <property name="games">
       <set>
           <value>cf</value>
       </set>
   </property>
   <!--7. null-->
   <property name="wife">
       <null/>
   </property>
   <!--8. Properties-->
   <property name="info">
       <props>
           <prop key="学号">2022</prop>
           <prop key="搞笑">小飞棍来喽</prop>
       </props>
   </property>
</bean>

 

拓展方式注入:

p命名空间注入:代表Set方式注入

c命名空间注入:代表构造器方式注入

 

命名空间

p命名空间: 引入第三方的约束: xmlns:p="http://www.springframework.org/schema/p"

c命名空间: xmlns:c="http://www.springframework.org/schema/c"

 

单例模式:

双重检测锁模式 的 懒汉式单例 (DCL 懒汉式) .java 文件 //懒汉式单例

public class LazyMan {
   private LazyMan() {
       System.out.println(Thread.currentThread().getName() + "ok");
  }

   /**
* 加一个 volatile 避免了 指令重排
*/
   private volatile static LazyMan LazyMan;

   //双重检测锁模式 的懒汉式单例 DCL懒汉
   public static LazyMan getInstance() {
       if (LazyMan == null) {
           synchronized (LazyMan.class) {
               if (LazyMan == null) {
                   LazyMan = new LazyMan();//不是一个原子性操作
                   /**
                       * 1.分配内存空间
                       * 2.执行构造方法,初始化对象
                       * 3.把这个对象指向这个空间
                       *
                       * 按照123执行,
                       * 单线程可以,123 132
                       * 多线程不行 这时候LazyMan 还没有完全构造
                       */
              }
          }
      }
       return LazyMan;
  }
}

.java 文件 //单例模式

public class Holder {
   //定义私有化构造函数
   private Holder() {
  }

   public static Holder getInstance() {
       return InnerClass.HOLDER;
  }

   //静态内部类
   public static class InnerClass {
       private static final Holder HOLDER = new Holder();
  }
}

枚举实现 单例模式 反射不能破坏枚举 (对于我们来说,或者官方规定不能破坏,但是狂神可以实现 使用反射破坏枚举) 反射机制可以破坏 单例模式 线程 检测锁 设计模式 单例模式 原型模式 spring

 

bean的作用域:

1.单例模式(Spring默认机制) 单例模式不能执行并发操作,会出现数据不一致 单线程使用 单例模式 <bean id="user2" class="com.kuang.pojo.user" c:age="18" c:name="狂神" scope="singleton" /> 2.原型模式:每次从容器中get的时候,都会产生一个新对象! 原型模式每次都需要产生一个新的对象,很浪费资源 多线程使用 原型模式 <bean id="accountservice" class="com.something.Defau1tAccountservice" scope="prototype" /> 3.其余的request.session、application、这些个只能在web开发中使用到!

 

Bean 的自动装配:

自动装配是Spring 满足 bean 依赖的一种方式 spring 会在上下文中,自动寻找,并自动给 bean 装配属性

spring  有三种装配的方式
1. xml 中显示的配置
2.Java中显示 的配置
3.隐式的自动装配bean (重要)

测试: 环境测试:一个人有两个宠物 byName 自动装配:

<!--使用 Spring 来创建对象,在 Spring 这些都称为 Bean,对象就是Bean-->
<bean id="cat" class="com.jing.pojo.Cat" name=""/>
<bean id="dog" class="com.jing.pojo.Dog" name=""/>
<!--
byName: 会自动在容器上下文中查找,和自己对象 set方法后面的值,对应的 bean id .
-->
<bean id="people" class="com.jing.pojo.People" name="" autowire="byName">
  <property name="name" value="xiaoming" />
</bean>

byType 自动装配:

<!--使用 Spring 来创建对象,在 Spring 这些都称为 Bean,对象就是Bean-->
<bean class="com.jing.pojo.Cat" name=""/>
<bean class="com.jing.pojo.Dog" name=""/>
<!--
byType: 会自动在容器上下文中查找,和自己对象 属性类型相同 的 bean id .
-->
<bean id="people" class="com.jing.pojo.People" name="" autowire="byType">
  <property name="name" value="xiaoming" />
</bean>

小结: . byname的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致! bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!

 

注解自动装配:

Autowired 直接在属性上使用即可!也可以在set方式上使用! 使用Autowired 我们可以不用编写Set方法了, 前提是你这个自动装配的属性在lOC(Spring)容器中存在,且符合名字byname! 科普: @Nu11able字段标记了这个注解,说明这个字段可以为nu11;

public @interface Autowired{
boolean required() default true;
}

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、 我们可以使用@Qualifier(value="xxx")去配置@Autowired的使用,指定一个唯一的bean对象注入!

public class People{
@Autowired
@Qua1ifier(value="cat111")
private cat cat;


@Autowired
@Qualifier(value="dog222")
private Dog dog;

private string name;

}

 

注解实现自动装配 小结: @Nullable 字段标记了这个注解,说明这个字段可以为nu11 @Resource和@Autowired的区别:都是用来自动装配的,都可以放在属性字段上. @Autowired 通过 byType 的方式实现,必须要求这个对象存在 @Resource 默认通过 byname 的方式实现,如果找不到名字,则通过byType实现! 执行顺序不同: @Autowired 通过 byType 的方式实现 @Resource 默认通过 byname 的方式实现

spring注解说明:

@Autowired : 自动装配通过类型。名字 如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="xxx")

@Nullable字段标记了这个注解,说明这个字段可以为null;

@Resource :自动装配通过名字。类型。

@Component :组件,放在类上,说明这个类被Spring管理了,就是bean!

@Component pojo 层 @Repository dao 层 @Service service 层 @Controller controller 层 上面四个注解功能一样,都是代表将某个类注册到Spring中,装配Bean 作用域:通过这个注解代替 @Scope("prototype")

值 通过这个注解代替 @Value("jing3")

spring注解 小结 xml与注解: xml更加万能,适用于任何场合!维护简单方便。 注解不是自己类使用不了,维护相对复杂! xml与注解最佳实践: xml用来管理bean; 注解只负责完成属性的注入; 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持

在Spring4之后,要使用注解开发,必须要保证aop的包导入了

这种纯Java的配置方式,在SpringBoot中随处可见! 见 spring-study的模块 spring-07-appconfig

posted @   kuaiquxie  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
历史上的今天:
2021-07-13 学习java 7.13
点击右上角即可分享
微信分享提示