Spring-IOC的理解

Spring-IOC的理解,第1张

Spring-IOC的思维导图

一、IOC原理

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

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建和组装对象(Bean)存入容器中,程序使用时再从Ioc容器中取出需要的对象。

之前的业务中,用户的需求会影响原来的代码,需要根据用户的需求去修改源代码。

使用一个Set接口实现,发生革命性的变化。

private UserDao userDao;

//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao){
    this.userDao = userDao;
}

  • 之前,程序使主动创建对象,控制权在程序猿手上
  • 使用set注入之后,程序不再具有主动性,变成了被动的接受对象

注入思想,从本质上解决了问题,程序员不用再去管理对象的创建了,降低了系统的耦合度。这是IOC的原型

二、通过IOC编写程序的步骤
  1. 编写一个实体类

    package com.zyx.pojo;
    
    public class Hello {
        private String str;
    
        public Hello() {
        }
    
        public Hello(String str) {
            this.str = str;
        }
    
        public String getStr() {
            return str;
        }
    
        public void setStr(String str) {
            this.str = str;
        }
    
        @Override
        public String toString() {
            return "hello{" +
                    "str='" + str + '\'' +
                    '}';
        }
    }
    
  2. 编写配置文件,applicationContext.xml

    
    <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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
        <bean id="hello" class="com.zyx.pojo.Hello">
            <property name="str" value="Spring"/>
        bean>
    
    beans>
    
  3. 测试

    public class MyTest {
        public static void main(String[] args) {
            //获取ApplicationContext:拿到Spring容器
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //我们的对象现在都在Spring中管理,要使用直接去里面取出来就可以
            //getBean : 参数即为spring配置文件中bean的id .
            Hello hello = (Hello) context.getBean("hello");
            System.out.println(hello.toString());
        }
    }
    
  4. Hello 对象是谁创建的 ? 【hello 对象是由Spring创建的】

  5. Hello 对象的属性是怎么设置的 ? 【 hello 对象的属性是由Spring容器设置的】

  6. 控制:传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的

  7. 反转:程序本身不创建对象 , 而变成被动的接收对象 .

三、Spring配置文件applicationContext.xml

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">



beans>
3.1 别名

alias 设置别名 , 为bean设置别名 , 可以设置多个别名


<alias name="userT" alias="userNew"/>
3.2 import

团队的合作通过import来实现 .

<import resource="{path}/applicationContext.xml"/>
3.3 Bean的配置

在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean,就是java对象。简单地讲,bean就是由IoC容器初始化、装配及管理的对象。

类型 变量名 = new 类型();
Hello hello = new Hello();

3.3.1 id

id = 变量名, 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符

3.3.2 name

如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;

3.3.3 class

bean 对象所对应的全限定名:包名 + 类型

3.3.4 property

property相当于给对象中的属性设置一个值

  1. ref:引用Spring容器中创建好的对象
  2. value:具体的值,基本数据类型
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
   <property name="name" value="Spring"/>
bean>
3.3.5 scope(Bean的作用域)
  1. 单例模式(Spring默认机制)

    <bean id="user" class="com.zyx.pojo.User" scope="singleton"/>
    
  2. 原型模式:每次从容器种get的时候,都会产生一个新对象

    <bean id="user" class="com.zyx.pojo.User" scope="prototype"/>
    
  3. Request(基于web的应用中使用)

  4. Session(基于web的应用中使用)

3.3.6 autowire(自动装配Bean) 四、依赖注入
  • 依赖注入

    • 依赖:bean对象的创建依赖于容器

    • 注入:bean对象中的所有属性,由容器来注入

4.1 构造器注入

POJO得有有参构造,通过有参构造方法来创建

  1. 实体类
public class User {

   private String name;

   public UserT(String name) {
       this.name = name;
  }

   public void setName(String name) {
       this.name = name;
  }

   public void show(){
       System.out.println("name="+ name );
  }

}
  1. 编写配置文件,applicationContext.xml

    1. 下标赋值
    
    <bean id="user" class="com.zyx.pojo.User">
        
        <constructor-arg index="0" value="xue"/>
    bean>
    
    1. 类型赋值(不建议使用)
    
    <bean id="user" class="com.zyx.pojo.User">
        <constructor-arg type="java.lang.String" value="xue"/>
    bean>
    
    1. 参数名(推荐使用)
    
    <bean id="user" class="com.zyx.pojo.User">
        
        <constructor-arg name="name" value="xue"/>
    bean>
    
  2. 测试

    @Test
    public void testT(){
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       UserT user = (UserT) context.getBean("user");
       user.show();
    }
    
4.2 Set方式注入【重点】

要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .

Set注入是指IoC容器通过成员变量的setter方法来注入被依赖对象。这种注入方式简单、直观,因而在Spring的依赖注入里大量使用。

  1. 编写pojo类

    package com.zyx.pojo;
    
    public class Address {
    
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
    package com.zyx.pojo;
    
    import java.util.*;
    
    public class Student {
    
        private String name;
        private Address address;
        private String[] book;
        private List<String> hobbys;
        private Map<String, String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    }
    
    
  2. 编写配置文件,applicationContext.xml

    
    <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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    beans>
    
    1. 常量注入
    <bean id="student" class="com.zyx.pojo.Student">
        <property name="name" value="xue"/>
    bean>
    
    1. Bean注入

      注意点:这里的值是一个引用,ref

      <bean id="address" class="com.zyx.pojo.Address">
          <property name="address" value="重庆"/>
      bean>
      
      <bean id="student" class="com.zyx.pojo.Student">
          
          <property name="name" value="xue"/>
          
          <property name="address" ref="address"/>
      bean>
      
    2. 数组注入

      <bean id="student" class="com.zyx.pojo.Student">
          
          <property name="name" value="xue"/>
          
          <property name="address" ref="address"/>
          
          <property name="book">
              <array>
                  <value>红楼梦value>
                  <value>西游记value>
                  <value>水浒传value>
              array>
          property>
      bean>
      
    3. List注入

      <property name="hobbys">
          <list>
              <value>听歌value>
              <value>敲代码value>
              <value>看电影value>
          list>
      property>
      
    4. Map注入

      <property name="card">
          <map>
              <entry key="身份z" value="1234444444444"/>
              <entry key="yhk" value="1234444444444"/>
          map>
      property>
      
    5. set注入

      <property name="games">
                  <set>
                      <value>LOLvalue>
                      <value>BOBvalue>
                      <value>COCvalue>
                  set>
      property>
      
    6. Null注入

      <property name="wife">
          <null/>
      property>
      
    7. Properties注入

      <property name="info">
          <props>
              <prop key="学号">20190515prop>
              <prop key="性别">prop>
              <prop key="姓名">小明prop>
          props>
      property>
      
  3. 测试类

    import com.zyx.pojo.Student;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            Student student = (Student) context.getBean("student");
            System.out.println(student.getAddress());
        }
    }
    
4.3 p命名空间和 c 命名空间
 public class User {
     private String name;
     private int age;
 }

1、P命名空间注入 : 需要在头文件中加入约束文件

 导入约束 : xmlns:p="http://www.springframework.org/schema/p"
 
 
<bean id="user" class="com.zyx.pojo.User" p:name="xue" p:age="18"/>

2、c 命名空间注入 : 需要在头文件中加入约束文件

c 就是所谓的构造器注入,需要把有参构造方法加上。

 导入约束 : xmlns:c="http://www.springframework.org/schema/c"
 
 
<bean id="user2" class="com.zyx.pojo.User" c:name="xue" c:age="18"/>
五、Bean的自动装配【重点】

感觉就是自动注入属性

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

Spring中bean有三种装配机制,分别是:

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配Bean【重要】

Spring的自动装配需要从两个角度来实现,或者说是两个 *** 作:

  1. 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
  2. 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;
5.1 测试环境搭建
  1. 编写实体类

    public class Cat {
        public String cat;
    
        public void shut(){
            System.out.println("miao");
        }
    
        @Override
        public String toString() {
            return "Cat{" +
                    "cat='" + cat + '\'' +
                    '}';
        }
    }
    
    public class Dog {
        public String dog;
    
        public void shut(){
            System.out.println("wang");
        }
        @Override
        public String toString() {
            return "Dog{" +
                    "dog='" + dog + '\'' +
                    '}';
        }
    }
    
    public class People {
        private Cat cat;
        private Dog dog;
        private String name;
    
        public People() {
        }
        public People(Cat cat, Dog dog, String name) {
            this.cat = cat;
            this.dog = dog;
            this.name = name;
        }
        public Cat getCat() {
            return cat;
        }
        public void setCat(Cat cat) {
            this.cat = cat;
        }
        public Dog getDog() {
            return dog;
        }
        public void setDog(Dog dog) {
            this.dog = dog;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "People{" +
                    "cat=" + cat +
                    ", dog=" + dog +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
  2. 编写Spring配置文件

    
    <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">
    
       <bean id="dog" class="com.zyx.pojo.Dog"/>
       <bean id="cat" class="com.zyx.pojo.Cat"/>
    
       <bean id="people" class="com.zyx.pojo.People">
           <property name="cat" ref="cat"/>
           <property name="dog" ref="dog"/>
           <property name="str" value="xue"/>
       bean>
    beans>
    
  3. 测试

    public class MyTest {
       @Test
       public void testMethodAutowire() {
           ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
           People people = (People) context.getBean("people");
           people.getCat().shut();
           people.getDog().shut();
      }
    }
    
5.2 使用Bean属性实现自动装配 5.2.1 ByName自动装配

autowire byName (按名称自动装配)

修改bean配置,增加一个属性 autowire=“byName”

<bean id="cat" class="com.zyx.pojo.Cat"/>
<bean id="dog" class="com.zyx.pojo.Dog"/>


<bean id="people" class="com.zyx.pojo.People" autowire="byName">
    <property name="name" value="xue"/>
bean>

小结:

当一个bean节点带有 autowire="byName"的属性时。

  1. 将查找class表示的类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
  2. 去spring容器中寻找是否有此字符串名称id的bean对象。
  3. 如果有,就取出注入;如果没有,就报空指针异常。
5.2.2 ByType自动装配

autowire byType (按类型自动装配)

使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

修改bean配置,增加一个属性 autowire=“byType”

<bean id="cat" class="com.zyx.pojo.Cat"/>
<bean id="dog" class="com.zyx.pojo.Dog"/>


<bean id="people" class="com.zyx.pojo.People" autowire="byType">
    <property name="name" value="xue"/>
bean>

小结:

  • byname的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
  • byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
5.3 使用注解实现自动装配

jdk1.5 支持的注解,spring2.5就支持注解了

要使用注解须知:

  1. 在spring配置文件中引入context文件头

    xmlns:context="http://www.springframework.org/schema/context"
    
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    
  2. 开启属性注解支持: context:annotation-config/

    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:annotation-config/>
    
    beans>
    
5.3.1 @Autowired
  • @Autowired是按类型自动装配的,不支持id匹配。
  • 直接在属性上使用@Autowired注解
  • 需要导入 spring-aop的包!
  • @Autowired(required=false) 说明:false,对象可以为null;true,对象必须存对象,不能为null。
//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;
5.3.2 @Qualifier(value=“id”)
  • 和@Autowired一起使用,@Qualifier不能单独使用。
  • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
5.3.3 @Resource
  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
  • 其次再进行默认的byName方式进行装配;
  • 如果以上都不成功,则按byType的方式自动装配。
  • 都不成功,则报异常。
5.3.4 @Resource和@Autowired的区别
  • @Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
  • @Autowired 通过 bytype的方式实现,而且必须要求这个对象存在【常用】。如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名
  • @Resource默认通过 byname的方式实现,如果找不到名字,则通过 bytype的方式实现,如果两个都找不到,就报错【常用】
  • 执行顺序不同。@Autowired先byType,@Resource先byName。
六、使用注解开发

在spring4之后,要使用注解开发,需要导入aop的包

使用注解需要导入context约束,增加注解支持


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xmlns:context="http://www.springframework.org/schema/context"      xsi:schemaLocation="http://www.springframework.org/schema/beans
   https://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

beans>
6.1 Bean的实现

之前都是使用 bean 的标签进行bean注入,但是实际开发中一般都会使用注解

1、配置扫描哪些包下的注解


<context:component-scan base-package="com.zyx.pojo"/>

2、在指定包下编写类,增加注解

@Component("user")
// 相当于配置文件中 
public class User {
   public String name = "xue";
}

3、测试

@Test
public void test(){
   ApplicationContext applicationContext =
       new ClassPathXmlApplicationContext("beans.xml");
   User user = (User) applicationContext.getBean("user");
   System.out.println(user.name);
}
6.1.1 @Component三个衍生注解

@Component有几个衍生注解,在web开发中,会按照mvc三层架构分层!

  • @Controller:web层
  • @Service:service层
  • @Repository:dao层

这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean

6.2 普通属性注入

使用注解注入属性

1、可以不用提供set方法,直接在直接名上添加@value(“值”)

@Component("user")
// 相当于配置文件中 
public class User {
    
    // 相当于配置文件中 
   @Value("xue")
   public String name;
}

2、如果提供了set方法,在set方法上添加@value(“值”);

@Component("user")
public class User {

   public String name;

   @Value("秦疆")
   public void setName(String name) {
       this.name = name;
  }
}
6.3 自动装配
  • @Autowired:自动装配,通过类型

    如果Autowired不能唯一自动装配上属性,则需通过@Qualifier(value=“xxx”)

  • @Nullable:字段标记了这个注解,说明这个字段可以为Null

  • @Resource:自动装配,通过名字、类型

6.4 作用域
  • 单例模式:@Scope(“singleton”):默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
  • 原型模式:@Scope(“prototype”):多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
6.5 小结

xml与注解:

  • xml更加万能,适用于任何场合,维护更加简单
  • 注解不是自己类是用不了,维护相对复杂

xml与注解的最佳实践

  • xml用来管理bean
  • 注解只负责完成属性的注入
  • 我们在使用的过程中,只需要注意一个问题:必须要让注解生效,需要开启注解的支持
  • 使用过程中, 可以不用扫描,扫描是为了类上的注解
<context:annotation-config/>  

作用:

  • 进行注解驱动注册,从而使注解生效
  • 用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册
  • 如果不扫描包,就需要手动配置bean
  • 如果不加注解驱动,则注入的值为null!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/720292.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存