02-spring框架—— IoC 控制反转

  控制反转(IoC,Inversion of Control),是一个概念,是一种思想。指将传统上由程序代
码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。

  控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。

通过容器实现对象的创建,属性赋值,依赖的管理。

  IoC 是一个概念,是一种思想,其实现方式多种多样。当前比较流行的实现方式是依赖
注入。应用广泛。

  依赖:classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA
对 classB 有依赖。

Ioc 的实现:
➢ 依赖查找:DL( Dependency Lookup ),容器提供回调接口和上下文环境给组件。
➢ 依赖注入:DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行
完成。

  依赖注入 DI 是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建
被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。

  Spring 的依赖注入对调用者与被调用者几乎没有任何要求,完全支持对象之间依赖关系
的管理。

  Spring  框架使用依赖注入(DI )实现 IoC 。

  Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称
为 Bean。Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式
来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。

2.1  开发工具准备

开发工具:idea2017 以上
依赖管理:maven

需要置 设置 maven  本机仓库:

 

2.2 Spring  的第一个

举例:01-primay

2.2.1  创建 maven 

quickstart模板

 

2.2.2  引入 maven  依赖 pom.xml

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.16.RELEASE</version>
</dependency>
<!--插件-->
<plugins>
  <plugin>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>3.1</version>
     <configuration>
       <source>1.8</source>
       <target>1.8</target>
     </configuration>
  </plugin>
</plugins>

2.2.3  定义接口与实体类

public interface SomeService {
  void doSome();
}
public class SomeServiceImpl implements SomeService {
  public SomeServiceImpl() {
    super();
    System.out.println("SomeServiceImpl无参数构造方法");
  }
  @Override
  public void doSome() {
    System.out.println("====业务方法doSome()===");
  }
}

 2.2.4  创建 Spring 

  在 src/main/resources/目录现创建一个 xml 文件,文件名可以随意,但 Spring 建议的名
称为 applicationContext.xml。

  spring 配置中需要加入约束文件才能正常使用,约束文件是 xsd 扩展名。

  使用约束文件的语法在:xsd-configuration.html。这个 xsd-configuration.html 文件位置是
在%SPRING_HOME%\docs\spring-framework-reference\html\xsd-configuration.html

  SPRING_HOME:是从 spring 官网下载的资源 spring-framework-4.3.16.RELEASE-dist.zip 解
压后的目录。

 

  注意,Spring 配置文件中使用的约束文件为 xsd 文件。若 Eclipse 中没有自动提示功能,
则需要将约束要查找的域名地址指向本地的 xsd 文件。相应的 xsd 文件在 Spring 框架解压目
录下的 schema 目录的相应子目录中。

  约束文件:xsd(xml schema definition) xml 文档结构定义。

  作用:验证 xml 文档的逻辑结构是否正确。
  1.定义一个 xml 文档中都有什么元素
  2.定义一个 xml 文档中都有什么属性
  3.定义一个 xml 文档中元素可以有哪些子元素,以及元素的顺序。
  4.定义一个 xml 文档中元素和属性的数据类型。

  这里需要的是 spring-beans.xsd 约束文件,故需要在 beans 子目录中查找相应版本
的约束文件。

<bean />:用于定义一个实例对象。一个实例对应一个 bean 元素。
id:该属性是 Bean 实例的唯一标识,程序通过 id 属性访问 Bean,Bean 与 Bean 间的依
赖关系也是通过 id 属性关联的。

2.2.5 定义测试类

@Test
    public void test01(){
        System.out.println( "Hello Spring!" );
        //定义Spring的配置文件, 配置文件是在类路径的根目录之下
        String config = "applicationContext.xml";

        //创建Spring的容器对象.根据Spring配置文件的位置,使用接口的不同实现类
        //如果Spring的配置文件是在类路径(classpath),使用ClassPathXmlApplicationContext
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        //从容器中获取对象 使用getBean("<bean>的id")
        SomeService service = (SomeService) ctx.getBean("someService");

        //调用业务方法
        service.doSome();
    }

 

2.2.6  使用 spring  创建 非自定义类对象

spring 配置文件加入 java.util.Date 定义:
<bean id="myDate" class="java.util.Date" />

MyTest 测试类中:
调用 getBean(“myDate”); 获取日期类对象。

2.2.7  容器接口和实现类

ApplicationContext  接口 (容器)

ApplicationContext 用于加载 Spring 的配置文件,在程序中充当“容器”的角色。其实现
类有两个。

 

A 、  配置文件在类路径下

  若 Spring 配置文件存放在项目的类路径下,则使用 ClassPathXmlApplicationContext 实现
类进行加载。

 @Test
    public void test01(){
        System.out.println( "Hello Spring!" );
        //定义Spring的配置文件, 配置文件是在类路径的根目录之下
        String config = "applicationContext.xml";

        //创建Spring的容器对象.根据Spring配置文件的位置,使用接口的不同实现类
        //如果Spring的配置文件是在类路径(classpath),使用ClassPathXmlApplicationContext
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        //从容器中获取对象 使用getBean("<bean>的id")
        SomeService service = (SomeService) ctx.getBean("someService");

        //调用业务方法
        service.doSome();
    }

 

B 、    配置文件在项目根路径下

  FileSystemXmlApplicationContext 实现类用来加载存放在项目根路径下或磁盘路径中的
spring 配置文件。

  下面是存放在项目根路径下的情况,该配置文件与 src 目录同级,而非在 src 中。

 

/**
     * 测试容器的其他使用方式, 在Spring的配置文件放在项目的根目录之下
     * 和 src  , target是同级的位置。
     *
     * 使用FileSystemXmlApplicationContext读取配置文件
     */
    @Test
    public void test02(){
        //spring.xml放在项目的根之下, 只给出文件名称
        String config ="spring.xml";
        ApplicationContext ctx = new FileSystemXmlApplicationContext(config);
        SomeService service = (SomeService) ctx.getBean("someService1");
        service.doSome();
    }

 

C 、 ApplicationContext 

  ApplicationContext 容器,会在容器对象初始化时,将其中的所有对象一次性全部装配好。
以后代码中若要使用到这些对象,只需从内存中直接获取即可。执行效率较高。但占用内存。

/**
     * 测试原型
     * 原型对象的创建时间?
     *  把创建对象的时间延迟了, 延迟到使用对象的时候,
     *  在执行getBean()时才创建对象。
     *
     * 优点:不占内存。
     * 缺点:获取对象的速度慢
     */
    @Test
    public void test07(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        SomeService service1 = (SomeService) ctx.getBean("service1");
        SomeService service2 = (SomeService) ctx.getBean("service1");
/*
        System.out.println(service1.hashCode() + "   " +service2.hashCode());
        if( service1 == service2){
            System.out.println("service1和service2是同一个对象");
        } else {
            System.out.println("service1和service2   不是  同一个对象");
        }*/

    }

 

D 、 用 使用 spring  容器 创建的 的 java 

 

2.3 Bean 

  举例:beanAssemble 项目
  Bean 的装配,即 Bean 对象的创建。容器根据代码要求创建 Bean 对象后再传递给代码
的过程,称为 Bean 的装配。

2.3.1  默认装配方式

  Spring 调用 Bean 类的无参构造器,创建空值的实例对象。

 

2.3.2  容器中 Bean 的作用域

  当通过 Spring 容器创建一个 Bean 实例时,不仅可以完成 Bean 的实例化,还可以通过
scope 属性,为 Bean 指定特定的作用域。Spring 支持多种作用域。

(1)singleton:单例模式。即在整个 Spring 容器中,使用 singleton 定义的 Bean 将是单例的,
叫这个名称的对象只有一个实例。默认为单例的。

(2)prototype:原型模式。即每次使用 getBean 方法获取的同一个<bean />的实例都是一个

新的实例。

(3)request:对于每次 HTTP 请求,都将会产生一个不同的 Bean 实例。

(4)session:对于每个不同的 HTTP session,都将产生一个不同的 Bean 实例。
注意:

1)对于 scope 的值 request、session 只有在 Web 应用中使用 Spring 时,该作用域才有效。

2)对于 scope 为 singleton 的单例模式,该 Bean 是在容器被创建时即被装配好了。

3)对于 scope 为 prototype 的原型模式,Bean 实例是在代码中使用该 Bean 实例时才进行
装配的。

 

2.4  基于 XML 的 的 DI

举例:项目 di-xml

2.4.1  注入分类

  bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化
是由容器自动完成的,称为注入。

  根据注入方式的不同,常用的有两类:设值注入、构造注入。

(1 )  设值注入( 掌握)

  设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、直观,因而
在 Spring 的依赖注入中大量使用。

A 、  简单类型
<?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">


    <!--声明Student对象-->
    <!--
        di: 依赖注入,就是给属性赋值。
        di:实现有两种语法:1)使用xml中的标签和属性 . 2)使用注解
        di的分类:
         1)设值注入:就是spring调用类的set方法,完成赋值,最常用的方式。
         2)构造注入:spring调用类的有参数构造方法,完成属性赋值。

        简单类型:spring中把String和java的基本数据类型都叫做简单类型。

        1.设值注入:spring调用类的set方法,在set方法中完成属性赋值。
          简单类型的设值注入:<property name="属性名" value="简单类型的属性值" />
          <bean id="xx" class="yyy">
             <property name="属性名" value="简单类型的属性值" /> 给一个属性赋值
             ...
             ...
          </bean>

    -->
    <bean id="myStudent" class="com.bjpowernode.ba01.Student" >
        <property name="name" value="lisi" /><!--setName(李四)-->
        <property name="age" value="20" /><!--setAge(20)-->
        <property name="sex" value="男" /><!--setSex()-->
    </bean>
</beans>

 

B 、 引用类型

  当指定 bean 的某属性值为另一 bean 的实例时,通过 ref 指定它们间的引用关系。ref
的值必须为某 bean 的 id 值。

<?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">


    <!--声明Student对象-->
    <!--
        di: 依赖注入,就是给属性赋值。
        di:实现有两种语法:1)使用xml中的标签和属性 . 2)使用注解
        di的分类:
         1)设值注入:就是spring调用类的set方法,完成赋值,最常用的方式。
         2)构造注入:spring调用类的有参数构造方法,完成属性赋值。

        简单类型:spring中把String和java的基本数据类型都叫做简单类型。

        1.设值注入:spring调用类的set方法,在set方法中完成属性赋值。
          简单类型的设值注入:<property name="属性名" value="简单类型的属性值" />
          <bean id="xx" class="yyy">
             <property name="属性名" value="简单类型的属性值" /> 给一个属性赋值
             ...
             ...
          </bean>


          引用类型的设值注入:使用ref来赋值
            ref有两种使用方式:
            1.ref作为属性
            <bean id="xx" class="yyy">
             <property name="属性名" ref="bean的id"/>
             ...
             ...
            </bean>
            2.ref作为子标签
             <bean id="xx" class="yyy">
             <property name="属性名">
               <ref bean="bean的id"/>
             </property>
             ...
             ...
            </bean>


    -->


    <!--ref作为属性-->
    <bean id="myStudent" class="com.bjpowernode.ba02.Student" >
        <property name="name" value="李四" />
        <property name="age" value="20" />
        <property name="school" ref="mySchool" /> <!--setSchool(mySchool) -->
    </bean>

    <!--ref作为子标签-->
    <bean id="myStudent2" class="com.bjpowernode.ba02.Student">
        <property name="name" value="张三" />
        <property name="age" value="22" />
        <property name="school">
            <ref bean="mySchool"/>
        </property>
    </bean>

    <!--声明School-->
    <bean id="mySchool" class="com.bjpowernode.ba02.School">
        <property name="name" value="北京大学" />
        <property name="address" value="北京的海淀区" />
    </bean>
</beans>

 

(2 )  构造注入( 理解)

  构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。即,使用构造器设
置依赖关系。

<constructor-arg />标签中用于指定参数的属性有:
➢ name:指定参数名称。
➢ index:指明该参数对应着构造器的第几个参数,从 0 开始。不过,该属性不要也行,
但要注意,若参数类型相同,或之间有包含关系,则需要保证赋值顺序要与构造器中的参数
顺序一致。

<?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">


    <!--声明Student对象-->
    <!--
        di: 依赖注入,就是给属性赋值。
        di:实现有两种语法:1)使用xml中的标签和属性 . 2)使用注解
        di的分类:
         1)设值注入:就是spring调用类的set方法,完成赋值,最常用的方式。
         2)构造注入:spring调用类的有参数构造方法,完成属性赋值。

        简单类型:spring中把String和java的基本数据类型都叫做简单类型。

        构造注入:spring调用类的有参数构造方法,在创建对象的同时,给属性赋值。
         使用的标签:  <constructor-arg>
           <constructor-arg>表示构造方法的一个参数
           属性:
            1. name : 表示构造方法的形参名
            2. index : 表示构造方法的参数位置, 从 0 开始
            3. value :表示简单类型的参数值
            4. ref  : 引用类型的参数值
    -->


    <!--使用name属性-->
    <bean id="myStudent" class="com.bjpowernode.ba03.Student" >
        <constructor-arg name="myage" value="22"/>
        <constructor-arg name="myname" value="张三" />
        <constructor-arg name="mySchool" ref="myXueXiao" />
    </bean>

    <!--使用index属性-->
    <bean id="myStudent2" class="com.bjpowernode.ba03.Student">
        <constructor-arg index="1" value="28" />
        <constructor-arg index="0" value="李四" />
        <constructor-arg index="2" ref="myXueXiao"/>
    </bean>

    <!--省略index-->
    <bean id="myStudent3" class="com.bjpowernode.ba03.Student">
        <constructor-arg value="周仓" />
        <constructor-arg value="24" />
        <constructor-arg ref="myXueXiao"/>
    </bean>

    <!--声明School-->
    <bean id="myXueXiao" class="com.bjpowernode.ba03.School">
      <property name="name" value="北京大学" />
      <property name="address" value="北京的海淀区" />
    </bean>

    <!--java.util.Date-->
    <bean id="myDate" class="java.util.Date">
        <property name="time" value="1557389873100"/> <!--setTime()-->
    </bean>

    <bean id="myfile" class="java.io.File">
        <constructor-arg name="parent" value="D:/course/19-Spring"/>
        <constructor-arg name="child" value="spring.txt"/>
    </bean>


</beans>

 

2.4.2  引用类型 属性自动注入

  对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为<bean/>标签
设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属
性)。根据自动注入判断标准的不同,可以分为两种:

  byName:根据名称自动注入
  byType: 根据类型自动注入

(1 ) byName 

  当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用
byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean
类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。

<?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按某种规则给引用类型完成赋值。常用的方式 byName, byType
        1.byName:按名称注入, java类中引用类型的属性名和spring容器(xml配置文件)<bean>的id
                 值一样的,且数据类型是一样的。 这样的bean能够赋值给引用类型。
          指定byName
          <bean id="xx" class="yyy" autowire="byName">
             简单类型的赋值
          </bean>
     -->

    <!--byName自动注入-->
    <bean id="myStudent" class="com.bjpowernode.ba04.Student" autowire="byName">
        <property name="name" value="李四" />
        <property name="age" value="22"/>
        <!--引用类型-->
        <!--<property name="school" ref="myXueXiao" />-->
    </bean>



    <!--声明School-->
    <bean id="school" class="com.bjpowernode.ba04.School">
      <property name="name" value="清华大学" />
      <property name="address" value="北京的海淀区" />
    </bean>



</beans>

 

(2 ) byType  方式自动注入

  使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,
要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子
类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配
哪一个了。

 

2.4.3  为应用指定多个 Spring  配置文件

  在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导致配置文件变
得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将
Spring 配置文件分解成多个配置文件。

包含关系的配置文件:

  多个配置文件中有一个总文件,总配置文件将各其它子文件通过<import/>引入。在 Java
代码中只需要使用总配置文件对容器进行初始化即可。

举例:

Spring 配置文件:

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">

   <!--总的配置文件, 主要作用是包含其他的多个配置文件, 总的文件中一般不定义对象的
       使用<import resource="配置文件"> 包含其他的配置文件。

       关键字 "classpath:" , 表示类路径,告诉spring到类路径中查找配置文件
   -->

    <!--包含其他的配置文件-->
    <!--
    <import resource="classpath:ba06/spring-school.xml"/>
    <import resource="classpath:ba06/spring-student.xml"/>
    -->
    <!--使用通配符,指定多个配置文件。
        通配符“*”,表示0或多个字符
        注意:总的文件名称(total.xml),不能包含在通配符的范围内,不能叫做spring-total.xml
    -->
    <import resource="classpath:ba06/spring-*.xml"/>



</beans>

  也可使用通配符*。但,此时要求父配置文件名不能满足*所能匹配的格式,否则将出现
循环递归包含。就本例而言,父配置文件不能匹配 spring-*.xml 的格式,即不能起名为
spring-total.xml。

2.5  基于注解的 DI

举例:di-annotation 项目
对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例。Spring 中使用注解,
需要在原有 Spring 运行环境基础上再做一些改变,完成以下三个步骤。
(1)pom.xml 加入 AOP 依赖。

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>4.3.16.RELEASE</version>
</dependency>

(2)需要更换配置文件头,加入 spring-context.xsd 约束。

  约 束 在 %SPRING_HOME%\docs\spring-framework-reference\html\xsd-configuration.html
文件中。

 

(3)需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。

<?xml version="1.0" encoding="UTF-8"?>
<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
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--声明组件扫描器(context:component),指定注解所在的包名,让框架找到注解-->
    <!--
       base-package:指定注解在项目中的包名,框架会扫描这个包和子包中所有类的注解,
                    按照注解的功能,创建对象,赋值属性。
    -->
    <context:component-scan base-package="com.bjpowernode.ba01" />

    <!--指定扫描多个包-->
    <!--第一种,使用多次扫描器,分别指定不同的包-->
    <context:component-scan base-package="com.bjpowernode.ba01"/>
    <context:component-scan base-package="com.bjpowernode.ba02"/>

    <!--第二种,使用分隔符(,或者;)指定多个包-->
    <context:component-scan base-package="com.bjpowernode.ba01;com.bjpowernode.ba02"/>

    <!--第三种,指定父包-->
    <context:component-scan base-package="com.bjpowernode" />

</beans>

 

指定多个包的三种方式:

1) 使用多个 context:component-scan 

 <!--第一种,使用多次扫描器,分别指定不同的包-->
    <context:component-scan base-package="com.bjpowernode.ba01"/>
    <context:component-scan base-package="com.bjpowernode.ba02"/>

 

2) 指定 base-package 的值使用分隔符
分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格。

逗号分隔:

<!--第二种,使用分隔符(,或者;)指定多个包-->
    <context:component-scan base-package="com.bjpowernode.ba01,com.bjpowernode.ba02"/>

 

分号分隔:

<!--第二种,使用分隔符(,或者;)指定多个包-->
    <context:component-scan base-package="com.bjpowernode.ba01;com.bjpowernode.ba02"/>

3)base-package 

  base-package 的值表示是基本包,容器启动会扫描包及其子包中的注解,当然也会扫描到
子包下级的子包。所以 base-package 可以指定一个父包就可以。

<!--第三种,指定父包-->
    <context:component-scan base-package="com.bjpowernode" />

 

或者最顶级的父包

<!--第三种,指定顶级父包-->
    <context:component-scan base-package="com" />

  但不建议使用顶级的父包,扫描的路径比较多,导致容器启动时间变慢。指定到目标包和合
适的。也就是注解所在包全路径。例如注解的类在 com.bjpowernode.beans 包中

2.5.1  定义 Bean  的注解@Component( 掌握)

  需要在类上使用注解@Component,该注解的 value 属性用于指定该 bean 的 id 值。
举例:di01

package com.bjpowernode.ba01;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

/**
 * Author: 动力节点
 * 2019/5/10
 *
 * @Component: 创建类的对象,等同于<bean />,默认是单例对象
 *    属性: value 表示对象的名称(<bean>的id)
 *    位置: 在类定义的上面,表示创建此类的对象。
 *
 * @Component(value = "myStudent")等价于
 * <bean id="myStudent" class="com.bjpowernode.ba01.Student"/>
 *
 * 和@Component功能相同的其他注解
 * 1.@Repository:放在Dao层的实现类上面,创建dao对象。这样的对象是访问数据库的
 * 2.@Service:放在Service层的实现类上面, 创建service对象,表示业务层对象,能够有事务功能
 * 3.@Controller:放在处理器类的上面,创建处理器对象,处理器对象能接收用户的请求。
 *
 * @Repository,@Service,@Controller都能创建对象,除此之外还有其他的功能。
 * 使用这三个注解,能够分层。
 *
 *
 */
//创建Student的对象名称叫做myStudent, 对象存放在spring容器中
//@Component(value = "myStudent")

//省略value
//@Component("myStudent2")

//不指定对象的名称, 框架会给对象默认名称,默认的值是类名首字母小写
//@Component
@Component("myStudent")
public class Student {

    private String name;
    private int age;

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

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

另外,Spring 还提供了 3 个创建对象的注解:
➢ @Repository 用于对 DAO 实现类进行注解
➢ @Service 用于对 Service 实现类进行注解
➢ @Controller 用于对 Controller 实现类进行注解

  这三个注解与@Component 都可以创建对象,但这三个注解还有其他的含义,@Service
创建业务层对象,业务层对象可以加入事务功能,@Controller 注解创建的对象可以作为处
理器接收用户的请求。

  @Repository,@Service,@Controller 是对@Component 注解的细化,标注不同层的对
象。即持久层对象,业务层对象,控制层对象。

  @Component 不指定 value 属性,bean 的 id 是类名的首字母小写。

2.5.2  简单 类型属性注入@Value( 掌握)

  需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。
使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加
到 setter 上。

package com.bjpowernode.ba02;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("myStudent")
public class Student {

    /**
     * @Value: 简单类型的属性赋值
     *   属性: value 是String类型的, 表示简单类型的属性值
     *   位置:
     *       1.在属性定义的上面, 无需set方法,常用的方式
     *       2.在set方法上面
     */
    @Value("张三01")
    private String name;


    private int age;

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

    @Value("28")
    public void setAge(int age) {
        System.out.println("setAge:"+age);
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

2.5.3 byType  自动注入@Autowired( 掌握)

  需要在引用属性上使用注解@Autowired,该注解默认使用按类型自动装配Bean的方式。
使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加
到 setter 上。

package com.bjpowernode.ba03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("myStudent")
public class Student {

    /**
     * @Value: 简单类型的属性赋值
     *   属性: value 是String类型的, 表示简单类型的属性值
     *   位置:
     *       1.在属性定义的上面, 无需set方法,常用的方式
     *       2.在set方法上面
     */
    @Value("张三")
    private String name;


    private int age;


    /**
     * 引用类型
     * @Autowired:引用类型的自动注入, 支持byName, byType.默认是byType
     *       位置:
     *         1.属性定义的上面,无需set方法,常用方式
     *         2.在set方法的上面
     */
    //byType
    @Autowired
    private School school;

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

    @Value("28")
    public void setAge(int age) {
        System.out.println("setAge:"+age);
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

代码第二部分

package com.bjpowernode.ba03;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * Author: 动力节点
 * 2019/5/9
 */
@Component("mySchool")
public class School {
    @Value("人民大学")
    private  String name;
    @Value("北京的海淀")
    private  String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

 

2.5.4 byName  自动注入@Autowired  与@Qualifier(掌握)

  需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的 value 属性用
于指定要匹配的 Bean 的 id 值。类中无需 set 方法,也可加到 set 方法上。

package com.bjpowernode.ba04;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("myStudent")
public class Student {

    /**
     * @Value: 简单类型的属性赋值
     *   属性: value 是String类型的, 表示简单类型的属性值
     *   位置:
     *       1.在属性定义的上面, 无需set方法,常用的方式
     *       2.在set方法上面
     */
    @Value("张三")
    private String name;


    private int age;


    /**
     * 引用类型
     * @Autowired:引用类型的自动注入, 支持byName, byType.默认是byType
     *       属性:required , boolean类型的,默认是true
     *          true:引用类型必须赋值成功,如果失败,程序报错,并终止执行
     *          false:引用类型赋值失败,程序正常执行, 引用类型的值是 null
     *       位置:
     *         1.属性定义的上面,无需set方法,常用方式
     *         2.在set方法的上面
     * byName注入需要两个注解:
     *  1.@Autowired
     *  2.@Qualifier(value="bean的id")
     */
    //byName
    @Autowired(
            required = false
    )
    @Qualifier("myXueXiao1111")
    private School school;

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

    @Value("28")
    public void setAge(int age) {
        System.out.println("setAge:"+age);

        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

代码第二部分

package com.bjpowernode.ba04;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * Author: 动力节点
 * 2019/5/9
 */
@Component("myXueXiao")
public class School {
    @Value("人民大学")
    private  String name;
    @Value("北京的海淀")
    private  String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

@Autowired 还有一个属性 required,默认值为 true,表示当匹配失败后,会终止程序运
行。若将其值设置为 false,则匹配失败,将被忽略,未匹配的属性值为 null。

 2.5.5 JDK  注解@Resource  自动注入(掌握)

  Spring提供了对jdk中@Resource注解的支持。@Resource注解既可以按名称匹配Bean,
也可以按类型匹配 Bean。 默认是按名称注入。使用该注解,要求 JDK 必须是 6 及以上版本。
@Resource 可在属性上,也可在 set 方法上。

(1 ) byType  注入引用类型

  @Resource 注解若不带任何参数,采用默认按名称的方式注入,按名称不能注入 bean,
则会按照类型进行 Bean 的匹配注入。

package com.bjpowernode.ba05;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component("myStudent")
public class Student {

    /**
     * @Value: 简单类型的属性赋值
     *   属性: value 是String类型的, 表示简单类型的属性值
     *   位置:
     *       1.在属性定义的上面, 无需set方法,常用的方式
     *       2.在set方法上面
     */
    @Value("张三")
    private String name;
    private int age;
    /**
     * 引用类型
     *
     * @Resource: 来自jdk,可以给引用类型赋值,spring框架支持这个注解的使用。
     *            默认是byName自动注入
     *
     *       位置:1.在属性定义的上面,无需set方法,推荐使用
     *             2.在set方法的上面
     */
    //默认是byName。先使用byName赋值,如果byName失败,再使用byType
    @Resource
    private School school;

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

    @Value("28")
    public void setAge(int age) {
        System.out.println("setAge:"+age);
       
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

第二部分代码

package com.bjpowernode.ba05;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * Author: 动力节点
 * 2019/5/9
 */
@Component("myXueXiao")
public class School {
    @Value("清华大学")
    private  String name;
    @Value("北京的海淀")
    private  String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

(2 ) byName  注入引用类型

  @Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean 的 id。

package com.bjpowernode.ba06;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component("myStudent")
public class Student {

    /**
     * @Value: 简单类型的属性赋值
     *   属性: value 是String类型的, 表示简单类型的属性值
     *   位置:
     *       1.在属性定义的上面, 无需set方法,常用的方式
     *       2.在set方法上面
     */
    @Value("张三")
    private String name;
    private int age;
    /**
     * 引用类型
     *
     * @Resource: 来自jdk,可以给引用类型赋值,spring框架支持这个注解的使用。
     *            默认是byName自动注入
     *       属性:name,指定bean的id(名称)
     *       位置:1.在属性定义的上面,无需set方法,推荐使用
     *             2.在set方法的上面
     */
    //只使用byName。
    @Resource(name = "myXueXiao")
    private School school;

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

    @Value("28")
    public void setAge(int age) {
        System.out.println("setAge:"+age);
       
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

第二部分代码

package com.bjpowernode.ba06;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * Author: 动力节点
 * 2019/5/9
 */
@Component("myXueXiao")
public class School {
    @Value("清华大学")
    private  String name;
    @Value("北京的海淀")
    private  String address;

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

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

2.5.6  注解与 XML 的 的

注解优点是:
⚫ 方便
⚫ 直观
⚫ 高效(代码少,没有配置文件的书写那么复杂)。

其弊端也显而易见:以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。

XML 方式优点是:
⚫ 配置和代码是分离的
⚫ 在 xml 中做修改,无需编译代码,只需重启服务器即可将新的配置加载。
xml 的缺点是:编写麻烦,效率低,大型项目过于复杂。

 

转载于:https://www.cnblogs.com/Tpf386/p/10988696.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值