【Spring】IoC控制反轉詳解


IOC(概念和原理)

  1. 什么是 IOC
    1. 控制反轉(Inversion of Control,縮寫為IoC),把對象創建和對象之間的調用過程,交給 Spring 進行管理
    2. 使用 IOC 目的:為了耦合度降低
    3. 做入門案例就是 IOC 實現
  2. IOC 底層原理
    1. xml 解析
    2. 工廠模式
    3. 反射
  3. 畫圖講解 IOC 底層原理

IOC(BeanFactory 接口)

  1. IOC 思想基於 IOC 容器完成,IOC 容器底層就是對象工廠
  2. Spring 提供 IOC 容器實現兩種方式:(兩個接口)
    1. BeanFactory:IOC 容器基本實現,是 Spring 內部的使用接口,不提供開發人員進行使用

      加載配置文件時不會創建對象,在獲取對象(使用)才去創建對象

    2. ApplicationContext:BeanFactory 接口的子接口,提供更多更強大的功能,一般由開發人員進行使用

      加載配置文件時候就會把在配置文件對象進行創建

  3. ApplicationContext 接口有實現類

IOC 操作 Bean 管理

概念

  1. 什么是 Bean 管理
    1. Bean 管理指的是兩個操作
    2. Spring 創建對象
    3. Spirng 注入屬性
  2. Bean 管理操作有兩種方式
    1. 基於 xml 配置文件方式實現
    2. 基於注解方式實現

基於 xml 方式

  1. 基於 xml 方式創建對象

    <!--配置 User 對象創建-->
    <bean id="user" class="com.spring5.User"></bean>
    1. 在 spring 配置文件中,使用 bean 標簽,標簽里面添加對應屬性,就可以實現對象創建
    2. 在 bean 標簽有很多屬性,介紹常用的屬性
      • id 屬性:唯一標識
      • class 屬性:類全路徑(包類路徑)
    3. 創建對象時候,默認也是執行無參數構造方法完成對象創建
  2. 基於 xml 方式注入屬性
    1. DI:依賴注入,就是注入屬性
  3. 第一種注入方式:使用 set 方法進行注入
    1. 創建類,定義屬性和對應的 set 方法

      /**
      * 演示使用 set 方法進行注入屬性
      */
      public class Book {
          //創建屬性
          private String bname;
          private String bauthor;
          //創建屬性對應的 set 方法
          public void setBname(String bname) {
              this.bname = bname;
          }
          public void setBauthor(String bauthor) {
              this.bauthor = bauthor;
          } 
      }
    2. 在 spring 配置文件配置對象創建,配置屬性注入

      <!--2 set 方法注入屬性-->
      <bean id="book" class="com.nemo.spring5.Book">
          <!--使用 property 完成屬性注入
              name:類里面屬性名稱
              value:向屬性注入的值
          -->
          <property name="bname" value="易筋經"></property>
          <property name="bauthor" value="達摩老祖"></property>
      </bean> 
  4. 第二種注入方式:使用有參數構造進行注入
    1. 創建類,定義屬性,創建屬性對應有參數構造方法

      /**
      + 使用有參數構造注入
      */
      public class Orders {
          //屬性
          private String oname;
          private String address;
          //有參數構造
          public Orders(String oname,String address) {
              this.oname = oname;
              this.address = address;
          } 
      }
    2. 在 spring 配置文件中進行配置

      <!--3 有參數構造注入屬性-->
      <bean id="orders" class="com.nemo.spring5.Orders">
          <constructor-arg name="oname" value="電腦"></constructor-arg>
          <constructor-arg name="address" value="China"></constructor-arg>
      </bean>
  5. p 名稱空間注入(了解)
    使用 p 名稱空間注入,可以簡化基於 xml 配置方式
    1. 第一步 添加 p 名稱空間在配置文件中

      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:p="http://www.springframework.org/schema/p"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/schema.xsd">
      </beans>
    2. 第二步 進行屬性注入,在 bean 標簽里面進行操作

      <!--2 set 方法注入屬性-->
      <bean id="book" class="com.nemo.spring5.Book" p:bname="九陽神功" p:bauthor="無名氏"></bean>

xml 注入其他類型屬性

  1. 字面量
    1. null 值

      <!--null 值-->
      <property name="address">
          <null/>
      </property>
    2. 屬性值包含特殊符號

      <!--屬性值包含特殊符號
       1 把<>進行轉義 &lt; &gt;
       2 把帶特殊符號內容寫到 CDATA
      -->
      <property name="address">
          <value><![CDATA[<<南京>>]]></value>
      </property>
  2. 注入屬性-外部 bean
    1. 創建兩個類 service 類和 dao 類
    2. 在 service 調用 dao 里面的方法
    3. 在 spring 配置文件中進行配置
    public class UserService {
        //創建 UserDao 類型屬性,生成 set 方法
        private UserDao userDao;
        public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
        }
        public void add() {
        System.out.println("service add...............");
        userDao.update();
        } 
    }
    <!--1 service 和 dao 對象創建-->
    <bean id="userService" class="com.nemo.spring5.service.UserService">
        <!--注入 userDao 對象
            name 屬性:類里面屬性名稱
            ref 屬性:創建 userDao 對象 bean 標簽 id 值
        -->
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <bean id="userDaoImpl" class="com.nemo.spring5.dao.UserDaoImpl"></bean>
  3. 注入屬性-內部 bean
    1. 一對多關系:部門和員工
      一個部門有多個員工,一個員工屬於一個部門
      部門是一,員工是多
    2. 在實體類之間表示一對多關系,員工表示所屬部門,使用對象類型屬性進行表示

      //部門類
      public class Dept {
          private String dname;
          public void setDname(String dname) {
              this.dname = dname;
          } 
      }
      //員工類
      public class Emp {
          private String ename;
          private String gender;
          //員工屬於某一個部門,使用對象形式表示
          private Dept dept;
          public void setDept(Dept dept) {
              this.dept = dept;
          }
          public void setEname(String ename) {
              this.ename = ename;
          }
          public void setGender(String gender) {
              this.gender = gender;
          } 
      }
    3. 在 spring 配置文件中進行配置

      <!--內部 bean-->
      <bean id="emp" class="com.nemo.spring5.bean.Emp">
          <!--設置兩個普通屬性-->
          <property name="ename" value="lucy"></property>
          <property name="gender" value="女"></property>
          <!--設置對象類型屬性-->
          <property name="dept">
          <bean id="dept" class="com.nemo.spring5.bean.Dept">
          <property name="dname" value="安保部"></property>
          </bean>
          </property>
      </bean>
  4. 注入屬性-級聯賦值
    1. 第一種寫法

      <!--級聯賦值-->
      <bean id="emp" class="com.nemo.spring5.bean.Emp">
          <!--設置兩個普通屬性-->
          <property name="ename" value="lucy"></property>
          <property name="gender" value="女"></property>
          <!--級聯賦值-->
          <property name="dept" ref="dept"></property>
      </bean>
      <bean id="dept" class="com.nemo.spring5.bean.Dept">
          <property name="dname" value="財務部"></property>
      </bean>
    2. 第二種寫法:需要用到 get 方法

      <!--級聯賦值--> 
      <bean id="emp" class="com.nemo.spring5.bean.Emp">
          <!--設置兩個普通屬性-->
          <property name="ename" value="lucy"></property>
          <property name="gender" value="女"></property>
          <!--級聯賦值-->
          <property name="dept" ref="dept"></property>
          <property name="dept.dname" value="技術部"></property>
      </bean>
      <bean id="dept" class="com.nemo.spring5.bean.Dept">
          <property name="dname" value="財務部"></property>
      </bean>

xml 注入集合屬性

  1. 注入數組類型屬性
  2. 注入 List 集合類型屬性
  3. 注入 Map 集合類型屬性
    1. 創建類,定義數組、list、map、set 類型屬性,生成對應 set 方法

      public class Stu {
          //1 數組類型屬性
          private String[] courses;
          //2 list 集合類型屬性
          private List<String> list;
          //3 map 集合類型屬性
          private Map<String,String> maps;
          //4 set 集合類型屬性
          private Set<String> sets;
          public void setSets(Set<String> sets) {
              this.sets = sets;
          }
          public void setCourses(String[] courses) {
              this.courses = courses;
          }
          public void setList(List<String> list) {
              this.list = list;
          }
          public void setMaps(Map<String, String> maps) {
              this.maps = maps;
          } 
      }
    2. 在 spring 配置文件進行配置

      <!--1 集合類型屬性注入-->
      <bean id="stu" class="com.nemo.spring5.collectiontype.Stu">
          <!--數組類型屬性注入-->
          <property name="courses">
              <array>
                  <value>java 課程</value>
                  <value>數據庫課程</value>
              </array>
          </property>
          <!--list 類型屬性注入-->
          <property name="list">
              <list>
                  <value>張三</value>
                  <value>小三</value>
              </list>
          </property>
          <!--map 類型屬性注入-->
          <property name="maps">
              <map>
                  <entry key="JAVA" value="java"></entry>
                  <entry key="PHP" value="php"></entry>
              </map>
          </property>
          <!--set 類型屬性注入-->
          <property name="sets">
              <set>
                  <value>MySQL</value>
                  <value>Redis</value>
              </set>
          </property>
      </bean>
  4. 在集合里面設置對象類型值

    <!--創建多個 course 對象-->
    <bean id="course1" class="com.nemo.spring5.collectiontype.Course">
        <property name="cname" value="Spring5 框架"></property>
    </bean>
    <bean id="course2" class="com.nemo.spring5.collectiontype.Course">
        <property name="cname" value="MyBatis 框架"></property>
    </bean>
    <!--注入 list 集合類型,值是對象-->
    <property name="courseList">
        <list>
            <ref bean="course1"></ref>
            <ref bean="course2"></ref>
        </list>
    </property>
    5、把集合注入部分提取出來
    1. 在 spring 配置文件中引入名稱空間 util

      <?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:p="http://www.springframework.org/schema/p"
             xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
      </beans>
    2. 使用 util 標簽完成 list 集合注入提取

      <!--1 提取 list 集合類型屬性注入-->
      <util:list id="bookList">
          <value>易筋經</value>
          <value>九陰真經</value>
          <value>九陽神功</value>
      </util:list>
      <!--2 提取 list 集合類型屬性注入使用--> 
      <bean id="book" class="com.nemo.spring5.collectiontype.Book">
          <property name="list" ref="bookList"></property>
      </bean>

FactoryBean

  1. Spring 有兩種類型 bean,一種普通 bean,另外一種工廠 bean(FactoryBean)
  2. 普通 bean:在配置文件中定義 bean 類型就是返回類型
  3. 工廠 bean:在配置文件定義 bean 類型可以和返回類型不一樣
    1. 第一步 創建類,讓這個類作為工廠 bean,實現接口 FactoryBean
    2. 第二步 實現接口里面的方法,在實現的方法中定義返回的 bean 類型
    public class MyBean implements FactoryBean<Course> {
        //定義返回 bean
        @Override
        public Course getObject() throws Exception {
            Course course = new Course();
            course.setCname("abc");
            return course;
        }
        @Override
        public Class<?> getObjectType() {
            return null;
        }
        @Override
        public boolean isSingleton() {
            return false;
        } 
    }
    <bean id="myBean" class="com.nemo.spring5.factorybean.MyBean"></bean>
    @Test
    public void test3() {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean3.xml");
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);
    }

bean 作用域

  1. 在 Spring 里面,設置創建 bean 實例是單實例還是多實例
  2. 在 Spring 里面,默認情況下,bean 是單實例對象
  3. 如何設置單實例還是多實例
    1. 在 spring 配置文件 bean 標簽里面有屬性(scope)用於設置單實例還是多實例
    2. scope 屬性值
      1. 第一個值 默認值,singleton,表示是單實例對象
      2. 第二個值 prototype,表示是多實例對象

    3. singleton 和 prototype 區別
      1. 第一 singleton 單實例,prototype 多實例
      2. 第二 設置 scope 值是 singleton 時候,加載 spring 配置文件時候就會創建單實例對象
        設置 scope 值是 prototype 時候,不是在加載 spring 配置文件時候創建 對象,在調用 getBean 方法時候創建多實例對象

bean 生命周期

  1. 生命周期
    1. 從對象創建到對象銷毀的過程
  2. bean 生命周期
    1. 通過構造器創建 bean 實例(無參數構造):此時會調用類的構造方法,產生一個新的對象
    2. 為 bean 的屬性設置值和對其他 bean 引用(調用 set 方法)
    3. 調用 bean 的初始化的方法(需要進行配置初始化的方法):此時對象已經創建好,但還沒有被正式使用,可能這里面需要做一些額外的操作(如預初始化數據庫的連接池)

      理解:看到這里可能會有讀者不理解,誒,屬性不是已經賦值完了嗎?不是已經初始化完了嗎?怎么還要調用初始化方法?
      這里我就來說說我的例子,不知道大家使用過一些“神奇的”依賴包沒有,一依賴,什么都不用做,什么都不用配置,自動生效,而這就是初始化的方法的用處所在了!!

    4. bean 可以使用了(對象獲取到了):此時對象已經完全初始化好,程序正常運行,對象被使用
    5. 當容器關閉時候,調用 bean 的銷毀的方法(需要進行配置銷毀的方法):此時對象准備被銷毀,已不再使用,需要預先的把自身占用的資源等處理好(如關閉、釋放數據庫連接),最后對象已經完全沒有被引用了,被垃圾回收器回收
  3. 演示 bean 生命周期

    public class Orders {
        //無參數構造
        public Orders() {
            System.out.println("第一步 執行無參數構造創建 bean 實例");
        }
        private String oname;
        public void setOname(String oname) {
            this.oname = oname;
            System.out.println("第二步 調用 set 方法設置屬性值");
        }
        //創建執行的初始化的方法
        public void initMethod() {
            System.out.println("第三步 執行初始化的方法");
        }
        //創建執行的銷毀的方法
        public void destroyMethod() {
            System.out.println("第五步 執行銷毀的方法");
        } 
    }
    <bean id="orders" class="com.nemo.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手機"></property>
    </bean>
    @Test
    public void testBean3() {
        // ApplicationContext context =
        // new ClassPathXmlApplicationContext("bean4.xml");
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("bean4.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("第四步 獲取創建 bean 實例對象");
        System.out.println(orders);
        //手動讓 bean 實例銷毀
        context.close();
    }
  4. bean 的后置處理器,bean 生命周期有七步
    1. 通過構造器創建 bean 實例(無參數構造)
    2. 為 bean 的屬性設置值和對其他 bean 引用(調用 set 方法)
    3. 把 bean 實例傳遞 bean 后置處理器的方法 postProcessBeforeInitialization
    4. 調用 bean 的初始化的方法(需要進行配置初始化的方法)
    5. 把 bean 實例傳遞 bean 后置處理器的方法 postProcessAfterInitialization
    6. bean 可以使用了(對象獲取到了)
    7. 當容器關閉時候,調用 bean 的銷毀的方法(需要進行配置銷毀的方法)
  5. 演示添加后置處理器效果
    1. 創建類,實現接口 BeanPostProcessor,創建后置處理器

      public class MyBeanPost implements BeanPostProcessor {
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("在初始化之前執行的方法");
              return bean;
          }
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("在初始化之后執行的方法");
              return bean;
          }
      }
      <!--配置后置處理器-->
      <bean id="myBeanPost" class="com.nemo.spring5.bean.MyBeanPost">
      </bean>

xml 自動裝配

  1. 什么是自動裝配
    1. 根據指定裝配規則(屬性名稱或者屬性類型),Spring 自動將匹配的屬性值進行注入
  2. 演示自動裝配過程
    1. 根據屬性名稱自動注入

      <!--實現自動裝配
          bean 標簽屬性 autowire,配置自動裝配
          autowire 屬性常用兩個值:
          byName 根據屬性名稱注入 ,注入值 bean 的 id 值和類屬性名稱一樣
          byType 根據屬性類型注入
      -->
      <bean id="emp" class="com.nemo.spring5.autowire.Emp" autowire="byName">
       <!--<property name="dept" ref="dept"></property>-->
      </bean>
      <bean id="dept" class="com.nemo.spring5.autowire.Dept"></bean>
    2. 根據屬性類型自動注入

      <!--實現自動裝配
          bean 標簽屬性 autowire,配置自動裝配
          autowire 屬性常用兩個值:
          byName 根據屬性名稱注入 ,注入值 bean 的 id 值和類屬性名稱一樣
          byType 根據屬性類型注入
      -->
      <bean id="emp" class="com.nemo.spring5.autowire.Emp" autowire="byType">
          <!--<property name="dept" ref="dept"></property>-->
      </bean>
      <bean id="dept" class="com.nemo.spring5.autowire.Dept"></bean>

外部屬性文件

連接池:
連接池的作用就是管理連接,因為如果單純的用JDBC去連接的話,頻繁的開啟 和關閉連接對於數據庫也是一種負擔。使用連接池技術后,可以不必頻繁開啟關閉連接 需要的時候就去用就好了,這樣是資源重用,而且有更快的系統反應速度

市面上實現作為連接池的方案有很多 c3p0 阿里的 druid(德魯伊) 等 都是很不錯的 實現方式

配置數據庫url 用戶 密碼 驅動等信息 管理連接

  1. 直接配置數據庫信息
    1. 配置德魯伊連接池
    2. 引入德魯伊連接池依賴 jar 包
    <!--直接配置連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
  2. 引入外部屬性文件配置數據庫連接池
    1. 創建外部屬性文件,properties 格式文件,寫數據庫信息
    2. 把外部 properties 屬性文件引入到 spring 配置文件中
      引入 context 名稱空間
    <beans xmlns="http://www.springframework.org/schema/beans" 
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           xmlns:p="http://www.springframework.org/schema/p" 
           xmlns:util="http://www.springframework.org/schema/util" 
           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/util http://www.springframework.org/schema/util/spring-util.xsd 
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 

    在 spring 配置文件使用標簽引入外部屬性文件

    <!--引入外部屬性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--配置連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClass}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.userName}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>

基於注解方式

  1. 什么是注解
    1. 注解是代碼特殊標記,格式:@注解名稱(屬性名稱=屬性值, 屬性名稱=屬性值..)
    2. 使用注解,注解作用在類上面,方法上面,屬性上面
    3. 使用注解目的:簡化 xml 配置
  2. Spring 針對 Bean 管理中創建對象提供注解
    1、@Service用於標注業務層組件
    2、@Controller用於標注控制層組件(如struts中的action)
    3、@Repository用於標注數據訪問組件,即DAO組件.
    4、@Component泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
    1. @Component

      @Bean@Component
      @Bean是創建一個對象並且設置值(一般是外部的對象) ,一般修飾一個方法,用來調用構造方法生成對象並設置屬性值;
      @Component是創建一個對象(一般是自己寫的對象) ,一般修飾一個

      原因:因為外部的對象我們手頭並沒有源碼,所以只能用@Bean的方式調用構造方法創建,並修改數據。
      而我們自己寫的代碼,可以任意修改。

    2. @Service
    3. @Controller
    4. @Repository

      上面四個注解功能是一樣的,都可以用來創建 bean 實例,加入到IoC容器中。
      注意:四個創建對象的注解功能其實是一樣的,可以混着用。他們實現一樣的功能,只是我們習慣區分標識,讓我們開發人員更加清晰,當前組件所扮演的角色,但是實際中把他們混用也是可以的。

  3. 基於注解方式實現對象創建
    1. 第一步 引入依賴
    2. 第二步 開啟組件掃描

      <!--開啟組件掃描
       1 如果掃描多個包,多個包使用逗號隔開
       2 掃描包上層目錄
      -->
      <context:component-scan base-package="com.nemo"></context:component-scan>
    3. 第三步 創建類,在類上面添加創建對象注解

      //在注解里面 value 屬性值可以省略不寫,
      //默認值是類名稱,首字母小寫
      //UserService -- userService
      @Component(value = "userService") //<bean id="userService" class=".."/>
      public class UserService {
          public void add() {
              System.out.println("service add.......");
          } 
      }
  4. 開啟組件掃描細節配置

    <!--示例 1
     use-default-filters="false" 表示現在不使用默認 filter,自己配置 filter
     context:include-filter ,設置掃描哪些內容
    -->
    <context:component-scan base-package="com.nemo" use-default￾filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
    <!--示例 2
     下面配置掃描包所有內容
     context:exclude-filter: 設置哪些內容不進行掃描
    -->
    <context:component-scan base-package="com.nemo">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
  5. 基於注解方式實現屬性注入
    1. @Autowired:根據屬性類型進行自動裝配
      1. 第一步 把 service 和 dao 對象創建,在 service 和 dao 類添加創建對象注解
      2. 第二步 在 service 注入 dao 對象,在 service 類添加 dao 類型屬性,在屬性上面使用注解
      @Service
      public class UserService {
          //定義 dao 類型屬性
          //不需要添加 set 方法
          //添加注入屬性注解
          @Autowired 
          private UserDao userDao;
          public void add() {
              System.out.println("service add.......");
              userDao.add();
          } 
      }
    2. @Qualifier:根據名稱進行注入
      這個@Qualifier 注解的使用,和上面@Autowired 一起使用

      //定義 dao 類型屬性
      //不需要添加 set 方法
      //添加注入屬性注解
      @Autowired //根據類型進行注入
      @Qualifier(value = "userDaoImpl1") //根據名稱進行注入
      private UserDao userDao;
    3. @Resource:可以根據類型注入,可以根據名稱注入

      注意:如果接口的實現類只有一個,那么可以根據類型來出入屬性;
      但是如果實現類有多個,那么就必須根據名字來注入屬性。

      //@Resource //根據類型進行注入
      @Resource(name = "userDaoImpl1") //根據名稱進行注入
      private UserDao userDao;
    4. @Value:注入普通類型屬性

      注意:開發中會用到@value去動態讀取服務器端口號,或者是配置環境是生產環境還是上線環境等等。。

      @Value(value = "abc")
      private String name; 
  6. 完全注解開發
    1. 創建配置類,替代 xml 配置文件

      @Configuration //作為配置類,替代 xml 配置文件
      @ComponentScan(basePackages = {"com.nemo"})
      public class SpringConfig {
      }
    2. 編寫測試類

      @Test
      public void testService2() {
          //加載配置類
          ApplicationContext context = 
              new AnnotationConfigApplicationContext(SpringConfig.class);
          UserService userService = context.getBean("userService", UserService.class);
          System.out.println(userService);
          userService.add();
      }

@Bean@Component

  • @Bean是創建一個對象並且設置值(一般是外部的對象) ,一般修飾一個方法,用來調用構造方法生成對象並設置屬性值;
  • @Component是創建一個對象(一般是自己寫的對象) ,一般修飾一個

    原因:因為外部的對象我們手頭並沒有源碼,所以只能用@Bean的方式調用構造方法創建,並修改數據。
    而我們自己寫的代碼,可以任意修改。

@Bean

我們拿MybatisPlus使用樂觀鎖來舉例子

首先需要在數據庫增加version字典,默認為1

然后在實體類增加對應的字段

// 樂觀鎖Version注解
@Version
private Integer version;

注冊組件,在MybatisPlusConfig中配置

// 注冊樂觀鎖
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    return new OptimisticLockerInterceptor();
}

小伙伴們看到了嗎?上面就是調用了構造方法來創建樂觀鎖對象,使用@Bean注冊。

@Component

上面說過了,@Component@Controller是一個東西,我們就拿控制器來舉例子吧。

@Controller
public class UserController {
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM