Spring5

来源:https://www.cnblogs.com/hanyk/archive/2022/04/28/16202135.html
-Advertisement-
Play Games

# Spring概述 1、Spring是輕量級開源JavaEE框架 2、Spring可以解決企業應用開發的複雜性 3、組成核心IOC、Aop IOC:控制反轉,把創建對象過程交給Spring進行管理 Aop:面向切麵,不修改源代碼進行功能增強 4、Spring特點 方便解耦,簡化開發 Aop編程支持 ...


    # Spring概述

1、Spring是輕量級開源JavaEE框架

2、Spring可以解決企業應用開發的複雜性

3、組成核心IOC、Aop

  • IOC:控制反轉,把創建對象過程交給Spring進行管理

  • Aop:面向切麵,不修改源代碼進行功能增強

4、Spring特點

  • 方便解耦,簡化開發
  • Aop編程支持
  • 方便程式測試
  • 方便集成各種優秀框架
  • 方便進行事務管理
  • 降低java api的使用難度

*此文檔版本為Spring5

IOC

什麼是IOC

​ (1)控制反轉,把對象的創建和對象之間調用的過程,交給Spring進行管理

​ (2) 使用IOC的目的:為了降低耦合

​ (3) 做入門案例就是IOC的實現

IOC底層原理

​ (1) xml解析、工廠模式、反射

image-20220223170558636

IOC過程 (進一步降低耦合度)

​ 第一步 xml配置文件,配置創建的對象

<bean id="dao" class="com.atguigu.UserDao"></bean>

​ 第二步 有service類和dao類 創建工廠類

class UserFactory{
	public static UserDao getDao(){
		String classValue = class屬性值;//1 xml解析 
        Class class = Class.forName(classValue);//2 通過反射創建對象
        return (UserDao)class.newInstance();//返回對象
	}
}	

IOC介面

  1. IOC思想基於IOC容器完成,IOC容器底層就是對象工廠

  2. Spring提供IOC容器實現兩種方式:(兩個介面)

  • BeanFactory :IOC容器基本實現,是Spring內部的使用介面,不提供給開發人員使用
    • 載入配置文件時不會創建對象,獲取\使用對象時才會創建對象
  • ApplicationContext :BeanFactory介面的子介面,提供更多更強大的功能,一般由開發人員使用
    • 載入配置文件時就會把配置文件中對象創建(伺服器啟動時創建)

ApplicationContext介面有實現類

image-20220223185151278

IOC操作 Bean管理

什麼是Bean管理

包含以下兩個操作

  1. Spring創建對象
  2. Spring註入屬性

Bean管理操作

1 bean創建對象

1 基於xml配置文件方式

<!--配置User對象創建-->
<bean id="user" class="com.atguigu.spring5.User"></bean>   

(1)在Spring配置文件中,使用bean標簽,標簽里添加對應屬性,就可以實現對象創建
(2)在bean標簽中有很多屬性:

  • id屬性:唯一標識(不能加特殊符號)

  • class屬性:類全路徑(包類路徑)

  • name:類似id(可添加特殊符號)

(3)創建對象的時候,預設也是執行無參構造方法

2 基於註解方式

2 基於xml註入屬性

(1) DI:依賴註入,就是註入屬性(DI是IOC的一種具體實現,在創建對象的基礎之上進行)

第一種註入方式:使用set方法進行註入

第一步:創建類、創建屬性、創建對應的set方法

public class Book {
    //創建屬性
    private String bname;
    private String bauthor;
    //創建屬性對應的set方法
    public void setBname(String bname) {
        this.bname = bname;
    }

    public void getBauthor(String bauthor) {
        this.bauthor = bauthor;
    }
}

第二步:在Spring配置文件配置對象創建,配置屬性註入

<!--2 set方法註入屬性-->
<bean id="book" class="com.atguigu.spring5.Book">
    <!--使用property完成屬性註入
        name:類裡面屬性名稱
        value:向屬性註入的值
    -->
    <property name="bname" value="張三日記"></property>
    <property name="bauthor" value="法外狂徒張三"></property>
</bean>
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;
    }
}
第二種註入方法:使用有參構造進行註入

第一步:創建類 ,定義屬性,創建屬性對應有參構造方法

/**
 * 使用有參構造註入
 * */

public class Orders {
    private String oname;
    private String address;

    public Orders(String oname,String address){
        this.oname = oname;
        this.address = address;
    }
}

第二步:在Spring的配置文件中進行配置

<!--3 使用有參構造註入屬性-->
<bean id="orders" class="com.atguigu.spring5.Orders">
    <!-- constructor-arg標簽用於有參構造註入屬性-->
    <constructor-arg name="oname" value="電腦"></constructor-arg>
    <constructor-arg name="address" value="China"></constructor-arg>
</bean>
第三種註入方式:P名稱空間註入(底層使用的還是set方法註入)

使用p名稱空間註入,可以簡化基於xml配置方式

  • 添加p名稱空間在配置文件中

image-20220224175509505

  • 進行屬性註入,在bean標簽裡面進行操作

    <!--4 使用p名稱空間註入-->
    <bean id="book" class="com.atguigu.spring5.Book" p:bname="張三的一生" p:bauthor="羅翔">
    </bean>
    
xml註入其他類型屬性

字面量:固定值

  1. null值

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

    <!--註入特殊符號
        1 拔尖括弧進行轉義 &lt;&gt;
        2 把特殊符號內容寫到CDATA
    -->
    <property name="address">
        <value><![CDATA[<<南京>>]]></value>
    </property>
    
註入屬性-外部bean
  1. 創建兩個類service類和dao類

  2. 在service調用dao裡面的方法

  3. 在Spring配置文件中進行文件配置

    <!--1 service和Dao對象創建-->
    <bean id="userService" class="com.atguigu.spring5.service.UserService">
        <!--註入userDao對象
            name屬性值:類裡面的屬性名稱
            ref屬性:創建userDao對象bean標簽id值
        -->
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>
    
    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();
    
            //原始方式:創建UserDao對象
    //        UserDao userDao = new UserDaoImpl();
    //        userDao.update();
        }
    }
    
註入屬性-內部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.atguigu.spring5.bean.Emp">
        <!--設置兩個普通屬性-->
        <property name="ename" value="lucy"></property>
        <property name="gender" value="女"></property>
    
        <!--設置對象類型屬性-->
        <property name="dept">
            <bean id="dept" class="com.atguigu.spring5.bean.Dept">
                <property name="dname" value="安保部門"></property>
            </bean>
        </property>
    </bean>
    
註入屬性-級聯賦值

第一種寫法

<!--級聯賦值-->
<bean id="emp" class="com.atguigu.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.atguigu.spring5.bean.Dept">
    <property name="dname" value="財務部"></property>
</bean>

第二種寫法 類中需要寫get方法

//員工類
public class Emp {
    private String ename;
    private String gender;
    //員工屬於某一個部門,使用對象形式表示
    private Dept dept;
    //生成dept的get方法

    public Dept getDept() {
        return 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;
    }

    public void add(){
        System.out.println(ename+"::"+gender+"::"+dept);
    }
}
<!--級聯賦值-->
<bean id="emp" class="com.atguigu.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.atguigu.spring5.bean.Dept">
    <property name="dname" value="財務部"></property>
</bean>
xml註入集合屬性
  1. 註入數組類型屬性

  2. 註入List集合屬性

  3. 註入Map集合類型屬性

  4. 註入set集合類型屬性

    創建類,定義數組、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> set;
    
        public void setSet(Set<String> set) {
            this.set = set;
        }
    
        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;
        }
    }
    

    在Spring配置文件進行配置

    <!--1 集合類型屬性註入-->
    <bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
        <!--數組類型屬性註入-->
        <property name="courses" >
            <array>
                <value>java課程</value>
                <value>sql課程</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="set">
            <set>
                <value>MySQL</value>
                <value>Redis</value>
            </set>
        </property>
    </bean>
    
  5. 在集合里設置對象類型值

    <!--註入list集合類型,值是對象-->
    <property name="courseList">
        <list>
            <ref bean="course1"></ref>
            <ref bean="course2"></ref>
        </list>
    </property>
    
    <!--創建多個course對象-->
    <bean id="course1" class="com.atguigu.spring5.collectiontype.Course">
        <property name="cname" value="Spring5框架"></property>
    </bean>
    <bean id="course2" class="com.atguigu.spring5.collectiontype.Course">
    <property name="cname" value="Mybatis框架"></property>
    
  6. 把集合註入部分提取出來

    1. 在Spring配置文件中引入空間名稱util
    <beans xmlns="http://www.springframework.org/schema/beans"
          	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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>
    
    1. 使用util標簽完成list集合註入提取

      <!--1 提取list集合類型屬性註入-->
      <util:list id="bookList" >
          <!--若引入對象使用ref標簽-->
          <value>張三日記</value>
          <value>張三的悔改</value>
          <value>法外狂徒</value>
      </util:list>
      
      <!--2 提取list集合類型屬性註入使用-->
      <bean id="book" class="com.atguigu.spring5.collectiontype.Book">
          <property name="list" ref="bookList"></property>
      </bean>
      

FactorBean

Spring里有兩種bean,一種普通的bean。另外一種是FactoryBean(Spring內置的)

  1. 普通bean

    Spring配置文件中定義bean類型即為返回類型

  2. FactoryBean

    Spring配置文件中定義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;
        }
    }
    
    //測試方法
    @Test
        public void testCollection3(){
            ApplicationContext context=new ClassPathXmlApplicationContext("bean3.xml");
            Course course=context.getBean("myBean",Course.class);
            System.out.println(course);
        }
    

    配置文件

    <bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean">
    </bean>
    

bean的作用域

  1. 在Spring里,預設設置下,bean是單實例對象

    @Test
    public void testCollection2(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");
        Book book1=context.getBean("book", Book.class);
        Book book2=context.getBean("book", Book.class);
        //book.test();
        System.out.println(book1);
        System.out.println(book2);
    }
    

輸出顯示地址相同為單實例對象:

image-20220303171118846

  1. 如何設置單實例或多實例

    (1)在Spring配置文件bean標簽裡面有用於設置的屬性(scope)

    (2)scope屬性值

    • 預設值:singleton,表示單實例對象
    • prototype,表示多實例對象
    <!--2 提取list集合類型屬性註入使用-->
    <bean id="book" class="com.atguigu.spring5.collectiontype.Book" scope="prototype">
        <property name="list" ref="bookList"></property>
    </bean>
    

    兩對象地址不同:

    image-20220303171843088

  2. singleton和prototype區別

    • singleton表示單實例,prototype多實例
    • 設置scope值是singleton時,載入Spring配置文件時就會創建單實例對象
    • 設置scope值是prototype時,不是在載入Spring配置文件時創建對象,在調用getBean方法時創建多例對象

Bean生命周期

從對象的創建到生命的銷毀的過程

bean生命周期:

  1. 通過構造器創建bean實例(無參數構造)

  2. 為bean的屬性設置值和對其他bean的引用(調用set方法)

    把bean實例傳給bean後置處理器的方法postProcessBeforeInitialization(bean的後置處理器BeanPostProcessor,bean共有7步)

  3. 調用bean初始化的方法(需要進行配置)

    把bean實例傳給bean後置處理器的另外一個方法postProcessAfterInitialization(bean的後置處理器BeanPostProcessor,bean共有7步)

  4. bean可以使用了(對象獲取到了)

  5. 當容器關閉時,調用bean的銷毀的方法(需要進行配置銷毀的方法)

    <bean id="orders" class="com.atguigu.spring5.bean.Orders" init-method="initMethod" destroy-method="destoryMethod">
        <property name="oname" value="手機"> </property>
    </bean>
    
    public class Orders {
        //1 無參構造
        public Orders(){
            System.out.println("第一步 執行無參構造方法創建bean實例");
        }
    
        private String oname;
        public void setOname(String oname) {
            this.oname = oname;
            System.out.println("第二步 調用set方法設置屬性值");
        }
    
        //3 創建執行的初始化方法
        public void initMethod(){
            System.out.println("第三步 執行初始化方法");
        }
        //5 創建執行的銷毀方法
        public void destoryMethod(){
            System.out.println("第五步 執行銷毀方法");
        }
    }
    
    //測試類
        @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();
        }
    

添加後置處理器之後:

  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.atguigu.spring5.bean.MyBeanPost"></bean>
    

IOC操作Bean管理(xml自動裝配)

什麼是自動裝配?

根據指定裝配規則(屬性名稱或屬性類型),Spring自動將匹配的屬性值進行註入

演示自動裝配過程:

根據屬性名稱自動註入

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

根據屬性類型自動註入

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

IOC操作Bean管理(外部屬性文件)

  1. 直接配置資料庫信息

    ​ 1.配置德魯伊連接池(Druid連接池,阿裡巴巴)

    ​ 2.引入德魯伊連接池依賴jar包

    <!--直接配置連接池-->
    <bean id="database" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="DriverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://locahost:3306/userDb"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    
  2. 引入外部屬性文件配置資料庫連接池

    (1)創建外部屬性文件,properties格式文件,寫資料庫信息

    properties文件存儲key:value格式配置

    prop.driverClass=com.mysql.jdbc.Driver
    prop.url=jdbc:mysql://localhost:3306/userDb
    prop.userName=root
    prop.password=root
    

    (2)把外部properties屬性文件引入到Spring配置文件中

    • 引入context名稱空間

      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:context="http://www.springframework.org/schema/context"
             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
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      </beans>
      
    • 在Spring配置文件標簽引入外部屬性文件

      <!--引入外部屬性文件-->
      <context:property-placeholder location="classpath:jdbc.properties"/>
      <!--配置連接池-->
          <bean id="database" 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>
      

IOC操作Bean管理(基於註解方式)

什麼是註解?

  • 註解是代碼特殊標記,格式:@註解名稱(屬性名稱=屬性值,屬性名稱=屬性值。。。)

  • 使用註解,註解作用在類、方法、屬性上面

  • 使用註解的目的:簡化xml配置

Spring針對Bean管理中創建對象提供註解:

  • @Component

  • @Service

  • @Controller

  • @Repository

    *四個註解功能相同,都可以用來創建bean對象

基於註解方式實現對象的創建:

  1. 引入依賴

  2. 開啟組件掃描

    <!--1 開啟組件掃描
            1 掃描多個包時,使用逗號隔開
            2 掃描包上層目錄可掃描包下多個包
    -->
    <context:component-scan base-package="com.atguigu"></context:component-scan>
    
  3. 創建類,在類上面添加創建對象註解

    //在註解裡面value屬性值可以不寫
    //預設值是類名稱,首字母小寫
    //UserService.class---userService
    @Service(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.atguigu" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>
    
    <!--示例2
        下麵示例掃描包下所有內容
        context:exclude-filter ,設置哪些不掃描
    -->
    <context:component-scan base-package="com.atguigu">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>
    
  5. 基於註解方式實現屬性註入

    • @AutoWired:根據屬性類型進行自動裝配

      ​ ①把service和dao對象創建,在service和dao類添加創建對象註解

      ​ ②在service註入dao對象,在service類添加dao類型屬性,在屬性前使用註解

      @Service(value = "userService")//<bean id="userService" class="..">相同
      public class UserService {
      
          //定義dao類型屬性
          //不需要添加set方法(spring已經封裝了這一步)
          //添加註入屬性的註解
          @Autowired
          private UserDao userDao;
          public void add(){
              System.out.println("service add....");
              userDao.add();
          }
      }
      
    • @Qualifier:根據屬性名稱進行註入

      此註解的使用需要與@Autowired一起使用

      @Repository(value = "userDaoImpl1")
      public class UserDaoImpl implements UserDao{
          @Override
          public void add() {
              System.out.println("dao add...");
          }
      }
      
      @Service(value = "userService")//<bean id="userService" class="..">相同
      public class UserService {
      
          //定義dao類型屬性
          //不需要添加set方法(spring已經封裝了這一步)
          //添加註入屬性的註解
          @Autowired  //根據類型進行註入
          @Qualifier(value = "userDaoImpl1")
          private UserDao userDao;
          public void add(){
              System.out.println("service add....");
              userDao.add();
          }
      }
      
    • @Resource:(javax中的註解,jdk11之後移除)可以根據類型註入,可以根據名稱註入

    //    @Resource//預設根據類型註入
        @Resource(name = "userDaoImpl1")
        private UserDao userDao;
    
    • @Value:註入普通類型屬性

      @Value(value = "abc")
      private String name;
      
  6. 完全註解開發

    (1)創建配置類,替代xml配置文件

    @Configuration//作為配置類,替代xml配置文件
    @ComponentScan(basePackages = {"com.atguigu"})
    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();
    }
    

AOP

什麼是AOP?

​ 面向切麵編程,利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各個部分之間的耦合度降低,提高程式的可重用性,同時提高開發效率。

通俗描述:可不修改源代碼,在主幹功能里添加新的功能

例子:在原登錄基礎上添加許可權判斷

image-20220308163433475

AOP底層原理

AOP底層使用動態代理

有兩種情況的動態代理

  1. 有介面的情況 ,使用JDK動態代理

    創建介面實現類代理對象,增強類的方法

    image-20220308164729412

  2. 沒有介面的情況 ,使用CGLIB動態代理

    創建子類的代理對象,增強類的方法

    image-20220308165207366

AOP底層原理(JDK動態代理)

使用JDK動態代理,使用Proxy類裡面的方法創建代理對象

image-20220308170122797

調用newProxyInstans方法

image-20220308170308516方法有三個參數:

  • 類載入器
  • 增強方法所在的類,這個類實現的介面,支持多個介面
  • 實現這個介面InvocationHandler,創建代理對象,寫增強方法

編寫JDK動態代理代碼:

  1. 創建介面,定義方法

    public interface UserDao {
        public int add(int a,int b);
        public String update(String id);
    }
    
  2. 創建介面實現類,實現方法(原功能)

    public class UserDaoImpl implements UserDao{
    
        @Override
        public int add(int a, int b) {
            return a+b;
        }
    
        @Override
        public String update(String id) {
            return id;
        }
    }
    
  3. 使用Proxy類創建介面代理對象(加新功能)

    public class JDKProxy {
        public static void main(String[] args){
    //        //創建介面實現類代理對象
            Class[] interfaces = {UserDao.class};
    //        Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
    //            @Override
    //            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //                return null;
    //            }
    //        });
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
            int result = dao.add(1,2);
            System.out.println("result:"+result);
        }
    }
    
    //創建代理對象代碼
    class UserDaoProxy implements InvocationHandler{
        //1 把創建的是誰的代理對象,把誰傳遞進來
        //有參數的構造
        private Object obj;
        public UserDaoProxy(Object obj){
            this.obj = obj;
        }
    
        //增強的邏輯
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            //方法之前
            System.out.println("方法之前執行。。。。"+method.getName()+":傳遞的參數。。。"+ Arrays.toString(args));
    
            //被增強的方法執行
            Object  res = method.invoke(obj,args);
    
            //方法之後
            System.out.println("方法之後執行。。。。"+obj);
    
            return res;
        }
    }
    

AOP(術語)

  1. 連接點:類裡面可以被增強的方法

  2. 切入點:類裡面實際被增強的方法

  3. 通知(增強):實際增強的邏輯部分(新加的部分)

    *假如add()方法被增強

    • 前置通知:add()之前執行的增強
    • 後置通知:add()之後執行的增強
    • 環繞通知:add()之前之後都執行的增強
    • 異常通知:add()異常時執行的增強
    • 最終通知:return之後執行的增強,後置通知之後,有異常時不執行
  4. 切麵(動作)

    把通知應用到切入點的過程

AOP操作(準備)

1、Spring框架中一般基於AspectJ實現AOP操作

AspectJ:AspectJ不是Spring組成部分,獨立AOP框架,一般把AspectJ和Spring框架一起使用,進行AOP操作

2、基於AspectJ實現AOP操作有兩種方式:

  1. 基於xml配置文件使用
  2. 基於註解方式實現(使用)

3、在項目工程里引入AOP相關依賴

image-20220309102111127

4、切入點表達式

  1. 切入點表達式的作用:知道對哪個類裡面哪個方法進行增強

  2. 語法結構:

    execution([許可權修飾符] [返回類型] [類全路徑] [方法名稱] ([參數列表]))

    例1:對com.atguigu.dao.BookDao類裡面的add方法進行增強

    execution(public void com.atguigu.dao.BookDao.add(int a,int b))

    許可權修飾符可省略,預設public

    返回類型可以用*號表示全類型

    execution(* com.atguigu.dao.BookDao.add(int a,int b))

    例2:對com.atguigu.dao.BookDao類裡面的所有方法進行增強

    execution(* com.atguigu.dao.BookDao.*(..))

    例3:對com.atguigu.dao包里的所有類,類里的所有方法進行增強

    execution(* com.atguigu.dao..(..))

AOP(AspectJ註解)

演示:

  1. 創建類,在類里定義方法

    public class User {
        public void add(){
            System.out.println("add...");
        }
    }
    
  2. 創建增強類

    1. 在增強類裡面,創建方法,讓不同方法代表不同通知類型

      //增強的類
      public class UserProxy {
      
          //前置通知
          public void before(){
              System.out.println("before...");
          }
      }
      
  3. 進行通知的配置

    1. 在Spring配置文件中,開啟註解的掃描

      <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"
             xmlns:aop="http://www.springframework.org/schema/aop"
             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
                                 http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd">
      
              <!--開啟註解掃描-->
              <context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
      </beans>
      
    2. 使用註解創建User和UserProxy對象

    3. 在增強類上面添加註解@Aspect

      //增強的類
      @Component
      @Aspect //生產代理對象
      public class UserProxy {
      
          //前置通知
          public void before(){
              System.out.println("before...");
          }
      }
      
    4. 在Spring配置文件中開啟生成代理對象

      <!--開啟Aspect生成代理對象-->
      <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
      
    5. 配置不同類型通知

      • 在增強類的裡面,在通知方法上面添加通知類型的註解,使用切入點表達式配置

      • @Before

      • @After

      • @AfterReturning

      • @AfterThrowing

      • @Around

      //增強的類
      @Component
      @Aspect //生產代理對象
      public class UserProxy {
      
          //前置通知
          //@Before註解表示前置通知
          @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void before(){
              System.out.println("before...");
          }
      
          @After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void after(){
              System.out.println("after...");
          }
      
          @AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void afterReturning(){
              System.out.println("afterReturning...");
          }
      
          @AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void afterThrowing(){
              System.out.println("afterThrowing...異常");
          }
      
          @Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
              System.out.println("around...之前");
      
              //被增強方法
              proceedingJoinPoint.proceed();
      
              System.out.println("around...之前後");
          }
      }
      
    6. 公共切入點

      //相同切入點抽取
      @Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")   //切入點註解
      public void pointdemo(){
      }
      
      //前置通知
      //@Before註解表示前置通知
      @Before(value = "pointdemo()")
      public void before(){
          System.out.println("before...");
      }
      
    7. 多個增強類對同一個切入點增強時,可設置優先順序

      在增強類上面加一個註釋@Order(數字類型值),數字類型值越小它的優先順序越高(值從0開始)

    8. 完全使用註解開發

      創建配置類(config),不需要創建xml配置文件

      @Configuration
      @ComponentScan(basePackages = "com.atguigu")    //開註解掃描
      @EnableAspectJAutoProxy(proxyTargetClass = true)    //開啟Aspect生成代理對象
      public class ConfigAop {
      }
      

AOP(AspectJxml配置文件)

  1. 創建兩個類:增強類和被增強類,創建方法

  2. 在Spring配置文件中創建兩個類的對象

  3. 在Spring配置文件中配置切入點

    <!-- 創建兩個類的對象-->
    <bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
    <bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
    
    <!-- 配置切入點-->
    <aop:config>
        <!-- 切入點-->
        <aop:pointcut id="buy" expression="execution(* com.atguigu.spring5.aopxml.Book.buy()) "/>
    
        <!-- 配置切麵(把增強應用到切入點的過程)-->
        <aop:aspect ref="bookProxy">
            <!-- 增強作用在具體方法上-->
            <aop:before method="before" pointcut-ref="buy"></aop:before>
        </aop:aspect>
    </aop:config>
    

JdbcTemplate

Spring框架對JDBC進行封裝,使用JdbcTemplate方便實現對資料庫操作

JdbcTemplate使用準備工作

  1. 引入相關jar包

    image-20220310175133948

  2. 在Spring配置文件中配置資料庫連接池

    <!--資料庫連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="name" value="jdbc:mysql:///user_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    </bean>
    
  3. 配置JdbcTemplate對象,註入Datasource

    <!--JdbcTemplate對象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--註入DataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
  4. 創建service類,創建dao類,在dao註入JdbcTemplate對象

    1. <!--1 開啟組件掃描-->
      <context:component-scan base-package="com.atguigu"></context:component-scan>
      
    2. @Service
      public class BookService {
          //註入Dao
          @Autowired
          private BookDao bookDao;
      }
      
    3. @Repository
      public class BookDaoImpl implements BookDao{
      
          //註入JdbcTemplate
          @Autowired
          private JdbcTemplate jdbcTemplate;
      }
      

JdbcTemplate操作資料庫(添加)

  1. 對應資料庫創建

  2. 編寫service和dao

    1. 在dao進行資料庫添加操作

      jdbcTemplate.update();
      
    2. 調用JdbcTemplate中的update()實現添加操作

      有兩個參數:

      1. sql語句
      2. 可變參數設置sql語句中的值
      
      @Repository
      public class BookDaoImpl implements BookDao{
      
          //註入JdbcTemplate
          @Autowired
          private JdbcTemplate jdbcTemplate;
      
      
          //添加方法
          @Override
          public void add(Book book) {
              //1 創建sql語句
              String sql="insert into t_book value(?,?,?)";
              //2 調用方法實現
              Object[] args = {book.getUser_id(),book.getUsername(),book.getUstatus()};
              int update = jdbcTemplate.update(sql,args);
              System.out.println(update);
          }
      }
      
    3. 測試類

      public class TestBook {
          @Test
          public void testJdbcTemplate(){
              ApplicationContext context=
                      new ClassPathXmlApplicationContext("bean1.xml");
              BookService bookServcie = context.getBean("bookService", BookService.class);
              Book book = new Book();
              book.setUser_id(1);
              book.setUsername("張三");
              book.setUstatus("a");
              bookServcie.addBook(book);
          }
      }
      

JdbcTemplate操作資料庫(修改和刪除)

  1. 方法的實現
//修改的方法
    @Override
    public void updateBook(Book book) {
        //1 創建sql語句
        String sql="update t_book set username=?,ustatus=? where user_id=?";
        //2 調用方法實現
        Object[] args = {book.getUsername(),book.getUstatus(),book.getUser_id()};
        int update = jdbcTemplate.update(sql,args);
        System.out.println(update);
    }

    //刪除的方法
    @Override
    public void deleteBook(String id) {
        //1 創建sql語句
        String sql="delete from t_book where user_id=?";
        //2 調用方法實現
        int update = jdbcTemplate.update(sql,id);
        System.out.println(update);
    }
  1. 測試

    public class TestBook {
        @Test
        public void testJdbcTemplate(){
            ApplicationContext context=
                    new ClassPathXmlApplicationContext("bean1.xml");
            BookService bookServcie = context.getBean("bookService", BookService.class);
    //        //添加
    //        Book book = new Book();
    //        book.setUser_id(1);
    //        book.setUsername("張三");
    //        book.setUstatus("a");
    //        bookServcie.addBook(book);
            //修改
            Book book = new Book();
            book.setUser_id(1);
            book.setUsername("javaupup");
            book.setUstatus("atguigu");
            bookServcie.updateBook(book);
    //        //刪除
    //        bookServcie.deleteBook("1");
        }
    

JdbcTemplate操作資料庫(查詢)

查詢返回某個值

  1. 場景:查詢表裡有多少條記錄,返回是某個值

  2. 使用JdbcTemplate實現查詢返回某個值

    jdbcTemplate.queryForObject(sql,Integer.class);
    

    有兩個參數:

    1. sql語句
    2. 返回類型Class
    //查詢表中的記錄數
    @Override
    public int selectCount() {
        String sql="SELECT COUNT(*) FROM t_book";
        Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
        return count;
    }
    

查詢返回對象

  1. 場景:查詢圖書詳情

  2. JdbcTemplate實現查詢返回對象

    jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(Book.class), id);

    三個參數:

    1. sql語句

    2. RowMapper,是介面,返回不同類型的數據,使用這個介面裡面的實現類完成數據封裝

    3. 傳遞sql語句中?(占位符)的值

      @Override
      public Book findBookInfo(int id) {
          String sql="SELECT * FROM t_book where user_id=?";
          //調用方法
          Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
      
          return book;
      }
      

查詢返回集合

  1. 場景:查詢圖書列表分頁

  2. 調用JdbcTemplate實現查詢返回集合

    jdbcTemplate.query(sql, new BeanPropertyRowMapper(Book.class));

    三個參數:

    1. sql語句

    2. RowMapper,是介面,返回不同類型的數據,使用這個介面裡面的實現類完成數據封裝

    3. 傳遞sql語句中?(占位符)的值

      *第三個參數也可不寫

      @Override
      public List<Book> findAllBook() {
          String sql = "select * from t_book";
          List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
          return bookList;
      }
      

JdbcTemplate操作資料庫(批量)

  1. 批量添加

    image-20220311202913560

    兩個參數:

    1. sql語句

    2. List集合,添加多條記錄數據

      //批量添加
      @Override
      public void batchAddBook(List<Object[]> batchArgs) {
          String sql = "insert into t_book value(?,?,?)";
          int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
          System.out.println(Arrays.toString(ints));
      }
      
  2. 批量修改

    @Override
    public void batchUpdateBook(List<Object[]> batchArgs) {
        String sql = "update t_book set username=?,ustatus=? where user_id=?";
        int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
        System.out.println(Arrays.toString(ints));
    }
    

    測試

    //批量修改
    List<Object[]> batchArgs = new ArrayList<>();
    Object[] objects1 = {"cc00","ccc00","3"};
    Object[] objects2 = {"dd00","ddd00","4"};
    Object[] objects3 = {"ee00","eee00","5"};
    batchArgs.add(objects1);
    batchArgs.add(objects2);
    batchArgs.add(objects3);
    bookServcie.batchUpdate(batchArgs);
    
  3. 批量刪除

    @Override
    public void batchDeleteBook(List<Object[]> batchArgs) {
        String sql="delete from t_book where user_id=?";
        int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
        System.out.println(Arrays.toString(ints));
    }
    

    測試

    List<Object[]> batchArgs = new ArrayList<>();
    Object[] objects1 = {"3"};
    Object[] objects2 = {"4"};
    Object[] objects3 = {"5"};
    batchArgs.add(objects1);
    batchArgs.add(objects2);
    batchArgs.add(objects3);
    bookServcie.batchDelete(batchArgs);
    

事務操作

1、事務是資料庫操作最基本單元,邏輯上一組操作,要麼都成功,如果有一個失敗則全失敗

典型場景:銀行轉賬:

  • lucy轉賬100元給mary
  • lucy少100,mary多100

2、事務的四個特性(ACID):

(1)原子性(atomicity):成功都成功,失敗都失敗

(2)一致性(consistency):操作之前和操作之後總量不變

(3)隔離性(isolation):多事務操作時,之間不會產生影響

(4)持久性(durability):提交之後表中數據就會發生變化

事務操作(搭建事務操作環境)

典型場景:銀行轉賬:

轉賬環境:image-20220311214628302

  1. 創建資料庫,添加記錄

image-20220311215159992

  1. 創建service,搭建dao,完成對象創建和註入關係

    1. service註入dao,在dao註入JdbcTemplate,在JdbcTemplate註入DateSource

    2. @Service
      public class UserService {
          //註入Dao
          @Autowired
          private UserDao userDao;
      
      }
      
    3. @Repository
      public class UserDaoImpl implements UserDao{
          @Autowired
          private JdbcTemplate jdbcTemplate;
      }
      
    4. <!--1 開啟組件掃描-->
      <context:component-scan base-package="com.atguigu"></context:component-scan>
      
      <!--資料庫連接池-->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
          <property name="url" value="jdbc:mysql:///user_db"/>
          <property name="username" value="root"/>
          <property name="password" value="root"/>
          <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
      </bean>
      
      <!--JdbcTemplate對象-->
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
          <!--註入DataSource-->
          <property name="dataSource" ref="dataSource"></property>
      </bean>
      
  2. 在dao創建兩個方:多錢和少錢,在service創建轉賬方法

  3. 以上代碼如果正常執行是沒有問題的,但是如果以上代碼出現異常,有問題,則應符合原子性和一致性,賬戶數據都不變

事務管理(Spring事務管理介紹)

  1. 事務一般添加到JavaEE三層結構里的service層(業務邏輯層)
  2. 在Spring進行事務管理操作有兩種方式
    1. 編程式事務管理
    2. 聲明式事務管理(常用)
  3. 聲明式事務管理
    1. 基於註解方式實現(常用)
    2. 基於xml配置文件方式
  4. 在Spring進行聲明式事務管理,底層使用AOP原理
  5. Spring事務管理API
    1. 提供了一個介面,代表事務管理器,這個介面針對不同的框架提供不同的實現類

image-20220312110914933

事務操作(註解聲明式事務管理)

  1. 在Spring配置文件配置事務管理器

    <!-- 創建事務管理器-->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 註入數據源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
  2. 在Spring配置文件中開啟事務註解

    1. 在Spring配置文件中引入名稱空間tx

      xmlns:tx="http://www.springframework.org/schema/tx"
      
    2. 開啟事務註解

      <!-- 開啟事務註解-->
      <tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>
      
  3. 在service類上面添加事務註解

    @Transactional
    
    1. 如果添加到類上面,則類中所有方法都添加事務
    2. 如果添加到方法上面,則只給此方法添加事務

事務操作(聲明式事務管理參數配置)

  1. 在service類上面添加@Transactional,在這個註解里可以配置事務相關的參數

    image-20220312113822417

    1. propagation:事務傳播行為

      *多事務方法直接進行調用,這個過程中事務是如何進行管理的

      image-20220312114612365image-20220312114741323

    2. isolation:事務隔離級別

      預設值:@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)

      *事務有特性稱為隔離性,多事務操作之間不會產生影響,不考慮隔離性會產生很多問題

      *有三個讀的問題:臟讀、不可重覆讀、虛(幻)讀

      • 臟讀:一個提交事務讀取到了另一個未提交事務的數據
      • 不可重覆度:一個未提交事務讀取到另一提交事務修改數據
      • 虛讀:一個未提交事務讀取到另一提交事務添加****數據

      解決:通過設置事務隔離級別就能解決讀問題

      image-20220312145603002

    3. timeout:超時時間

      • 事務需要在一定時間內提交,如果不提交就會進行回滾
      • 預設值:-1(不超時)
      • 設置以秒為單位
    4. readOlay:是否只讀

      • 讀:查詢操作;寫:添加修改刪除操作
      • 預設值:false(表示可以讀也可以寫)
      • 設置成true時只能讀不能寫
    5. rollbackFor:回滾

      • 設置出現哪些異常進行事務回滾
    6. noRollbackFor:不回滾

      • 設置出現哪些異常不進行事務回滾

事務操作(xml聲明式事務管理)

  1. 在Spring管理文件中進行配置

    1. 配置事務管理器

    2. 配置通知

    3. 配置切入點和切麵

      <!--1 創建事務管理器-->
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <!-- 註入數據源-->
              <property name="dataSource" ref="dataSource"></property>
          </bean>
          <!--2 配置通知-->
          <tx:advice id="txadvice">
              <!--配置事務參數-->
              <tx:attributes>
                  <!--指定在哪種規則的方法上面添加事務-->
                  <tx:method name="accountMoney" propagation="REQUIRES_NEW" isolation="REPEATABLE_READ" read-only="false"/>
      <!--            <tx:method name="account*"/>-->
              </tx:attributes>
          </tx:advice>
          <!--3 配置切入點和切麵-->
          <aop:config>
      <!--        切入點-->
              <aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
      <!--        切麵-->
              <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
          </aop:config>
      

事務操作(完全註解聲明式註解管理)

創建配置類,使用配置類代替xml配置文件

@Configuration  //配置類
@ComponentScan(basePackages = "com.atguigu")    //組件掃描
@EnableTransactionManagement    //開啟事務
public class TxConfig {
    //1. 創建資料庫連接池
    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql:///user_db");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        return druidDataSource;
    }
    //2. 創建JdbcTemplate對象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
        //到IOC容器中根據類型找到DateSource
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        //註入DateSource
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    //3. 創建事務管理器對象
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

Spring5框架新功能

整個Spring5框架基於java8,運行時相容JDK9,許多不建議使用的類和方法在代碼庫中刪除

Spiring5框架自帶了通用的日誌框架

  • Spring5已經移除了Log4jConfigListener,官方建議使用Log4j2
  • Spring5框架整合Log4j2

Log4j2使用:

1. 引入jar包

image-20220312160311370

  1. 創建Log4j2.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!--日誌級別以及優先順序排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
    <!--Configuration後面的status用於設置log4j2自身內部的信息輸出,可以不設置,當設置成trace時,可以看到log4j2內部各種詳細輸出-->
    <?import org.apache.logging.log4j.core.layout.PatternLayout?>
    <configuration status="INFO">
        <!--先定義所有的appender-->
        <appenders>
            <!--輸出日誌信息到控制台-->
            <console name="Console" target="SYSTEM_OUT">
                <!--控制日誌輸出的格式-->
                <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            </console>
        </appenders>
        <!--然後定義logger,只有定義了logger並引入的appender,appender才會生效-->
        <!--root:用於指定項目的根日誌,如果沒有單獨指定Logger,則會使用root作為預設的日誌輸出-->
        <loggers>
            <root level="info">
                <appender-ref ref="Console"/>
            </root>
        </loggers>
    </configuration>
    

Spring5框架核心容器支持@Nullable註解

@Nullable註解可以使用在方法上面,屬性上面,參數上面,表示方法返回可以為空,屬性值可以為空,參數值可以為空

Spring5核心容器支持函數風格GenericApplicationContext(lambda表達式)

public void testGenericApplicationContext(){
        //創建GenericApplicationContext對象
        GenericApplicationContext context = new GenericApplicationContext();
        //調用context方法註冊對象
        context.refresh();
        context.registerBean("user1",User.class,()-> new User());
        //獲取Spring註冊的對象
//        User user = (User) context.getBean("com.atguigu.spring5.test.User");
        User user = (User) context.getBean("user1");
        System.out.printl

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 兄弟們,上一個系列大家多少有點不太喜歡,那今天上點不一樣的。 來吧,直接整活~ 先準備一下 首先咱們需要安裝一下這兩個第三方模塊 requests >>> # pip install requests parsel >>> # pip install parsel 不會安裝的小伙伴,鍵盤按住win+ ...
  • 來源:https://blog.csdn.net/qq_48289488/article/details/121905018 Podman 簡介 什麼是Podman? Podman 是一個開源的容器運行時項目,可在大多數 Linux 平臺上使用。Podman 提供與 Docker 非常相似的功能。正 ...
  • 餅圖常用於統計學模塊,畫餅圖用到的方法為:pie( ) 一、pie()函數用來繪製餅圖 pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False, labeldistance= ...
  • 目前【騰訊雲簡訊】為客戶提供【國內簡訊】、【國內語音】和【海外簡訊】三大服務,騰訊雲簡訊SDK支持以下操作: 國內簡訊 國內簡訊支持操作: • 指定模板單發簡訊 • 指定模板群發簡訊 • 拉取簡訊回執和簡訊回覆狀態 海外簡訊 海外簡訊支持操作: • 指定模板單發簡訊 • 指定模板群發簡訊 • 拉取短 ...
  • 前言 最近在學習java,遇到了一個經典列印題目,空心金字塔,初學者記錄,根據網上教程,有一句話感覺很好,就是先把麻煩的問題轉換成很多的簡單問題,最後一一解決就可以了,然後先死後活,先把程式寫死,後面在改成活的。 如下圖是空心金字塔最終的實現效果,先要求用戶輸入層數然後輸出 一.普通矩形 首先我們先 ...
  • 近日,New Relic發佈了最新的2022 Java生態系統報告,這份報告可以幫助我們深入的瞭解Java體系的最新使用情況,下麵就一起來看看2022年,Java發展的怎麼樣了,還是Java 8 YYDS嗎? Java 11成為新的標準 在2020年的時候,Java 11已經推出了1年多,但當時Ja ...
  • 框架,本質上是一些實用經驗集合。即是前輩們在實際開發過程中積攢下來的實戰經驗,累積成一套實用工具,避免你在開發過程中重覆去造輪子,特別是幫你把日常中能遇到的場景或問題都給屏蔽掉,框架的意義在於屏蔽掉開發的基礎複雜度、屏蔽掉此類共性的東西,同時建立嚴格的編碼規範,讓框架使用者開箱即用,並且只需要關註差... ...
  • 前言 又到了每日分享Python小技巧的時候了,今天給大家分享的是Python中兩種常見的數據類型合併方法。好奇知道是啥嗎?就不告 訴你,想知道就往下看呀。話不多說,直接上… 1 合併字典 在某些場景下,我們需要對兩個(多個)字典進行合併。例如需要將如下兩個字典進行合併: 1 dict1 = {"a ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...