Spring5框架入門基礎

来源:https://www.cnblogs.com/Enid/archive/2023/11/07/17815763.html
-Advertisement-
Play Games

Spring5框架概述 Spring是輕量級的開源的JavaEE框架。 Spring可以解決企業應用開發的複雜性。 Spring有兩個核心部分:IOC和AOP IOC:控制反轉,把創建對象過程交給Spring進行管理 AOP:面向切麵,不修改源代碼進行功能增強 Spring特點 方便解耦,簡化開發( ...


Spring5框架概述

  • Spring是輕量級的開源的JavaEE框架

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

  • Spring有兩個核心部分:IOCAOP

    1. IOC:控制反轉,把創建對象過程交給Spring進行管理
    2. AOP:面向切麵,不修改源代碼進行功能增強
  • Spring特點

    1. 方便解耦,簡化開發(IOC可以降低耦合性)
    2. AOP編程支持
    3. 方便程式測試(Spring對Junit4支持,可以通過註解方便的測試Spring程式)
    4. 方便和其他框架進行整合
    5. 方便進行事務操作
    6. 降低API開發難度
  • Spring5系統結構

    img



IOC

概念和原理

什麼是IOC

  1. 控制反轉,把對象創建和對象之間的調用過程,交給Spring進行管理
  2. 使用IOC目的:為了降低耦合度

IOC底層原理

xml解析工廠模式反射

  • 原始方式與工廠模式的對比

    img

  • 畫圖講解IOC底層原理

    img


IOC之BeanFactory介面

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

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

    • BeanFactory:IOC容器基本實現,是Spring內部的使用介面不提供開發人員進行使用

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

    • ApplicationContextBeanFactory介面的子介面,提供更多更強大的功能,一般由開發人人員進行調用

      載入配置文件時會把在配置文件對象進行創建

  3. ApplicationContext介面有實現類

    img

    1. FileSystemXmlApplicationContext

      configLocation:要寫上配置文件在系統盤(某個盤)里的路徑

    2. ClassPathXmlApplicationContext

      configLocation:要寫上類路徑


IOC操作Bean管理

概念

  1. 什麼是Bean管理

    Bean管理指的是兩個操作:Spring創建對象Spring註入屬性

  2. Bean管理操作的方式:

    1. 基於xml配置文件方式實現
    2. 基於註釋方式實現

基於xml方式

  1. 創建對象

    <!--配置User對象創建-->
    <bean id="user" class="com.atguigu.spring.User"></bean>
    
    1. 在Spring配置文件中,使用bean標簽標簽裡面添加對應屬性,就可以實現對象創建
    2. bean標簽常用的屬性
      • id屬性:唯一標識
      • class屬性:類全路徑(包類路徑)
    3. 創建對象時候,預設執行無參構造方法
  2. 註入屬性

    • DI:依賴註入(Dependency Injection),就是註入屬性

      DI是一種設計模式,用於管理對象之間的依賴關係,它將創建和管理對象的責任轉移給了第三方的容器或框架,從而降低了系統的耦合度。

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

      1. 創建類,定義屬性和對應的set方法

         /**
           * 演示set方法註入屬性
           */
          public class Book {
              //創建屬性
              private String bname;
              private String bauthor;
          
              //創建屬性對應set方法
              public void setBauthor(String bauthor) {
                  this.bauthor = bauthor;
              }
              public void setBname(String bname) {
                  this.bname = bname;
              }
          }
        
      2. Spring配置文件配置對象創建,配置屬性註入

        <!--set方法註入屬性-->
        <bean id="book" class="com.atguigu.spring5.Book">
            <!--使用property完成屬性註入
                name:類裡面屬性名稱
                value:向屬性註入的值
        	-->
            <property name="bname" value="易筋經"></property>
            <property name="bauthor" value="達摩老祖"></property>
        </bean>
        
    2. 第二種註入方式:使用有參構造進行註入

      1. 創建類,定義屬性,創建屬性對應的有參構造方法

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

        <!--用有參構造註入屬性-->
        <bean id="orders" class="com.atguigu.spring5.Orders">
                <constructor-arg name="oname" value="電腦"></constructor-arg>
                <constructor-arg name="address"value="China"></constructor-arg>
        </bean>
        
    3. 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/spring-beans.xsd"></beans>
        
        
      2. 進行屬性註入,在bean標簽裡面進行操作

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

xml註入其他類型屬性

  • 字面量

    1. null值

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

      <!--屬性值包含特殊符號
               1. 把<>進行轉義 &lt;&gt;
               2. 把帶特殊符號內容寫到CDATA
        -->
      <property name="address">
          <value><![CDATA[<<南京>>]]></value>
      </property>
      
  • 註入屬性——外部bean

    1. 創建兩個類service類dao類

      package com.atguigu.spring5.dao;
      public interface UserDao{
      	public void update();
      }
      
      package com.atguigu.spring5.dao;
      public class UserDaoImpl implements UserDao{
          @Override
          public void update(){
              System.out.println("dao update...........");
          }
      }
      
    2. service調用dao裡面的方法

      package com.atguigu.spring5.service;
      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();
      
      
          }
      }
      
    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>
      
  • 註入屬性——內部bean

    1. 一對多關係

    比如:部門和員工,一個部門有多個員工,一個員工屬於一個部門。

    1. 在實體類之間表示一對多關係:員工使用對象類型屬性進行表示所屬部門

      //部門類
      public static Dept{
          private String dname;
          public void setDname(String dname){
              this.dname=dnamel
          }
      }
      
      //員工類
      public static Emp{
          private String name;
          private String gender;
          private Dept dept;  //用對象表示員工所屬的部門
          
          public void setName(String name){
              this.name = name;
          }
          public void setGender(String gender){
              this.gender = gender;
          }
      }
      
    2. Spring配置文件

      <!--內部bean-->
      <bean id="Emp" class="com.gtguigu.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>
      
  • 註入屬性——級聯賦值

    1. 第一種寫法

      <!--級聯賦值-->
      <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>
      
    2. 第二種寫法

      //使用對象形式表示員工屬於某一個部門
      private Dept dept;
      //生成dept的get方法
      public Dept getDept(){
          return dept;
      }
      public void setDept(Dept dept){
          this.dept = 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集合類型屬性

第一步,創建類,定義數組ListMapSet類型屬性,生成對應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 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;
    }

    public void setSets(Set<String> sets) {
        this.sets = sets;
    }
}

第二步,在Spring配置文件進行配置

<!--1 集合類型屬性的註入-->
<bean id="stu" class="com.atguigu.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>
  1. 在集合裡面設置對象類型值

    <!--創建多個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>
    </bean>
    <!--註入list集合類型,值是對象-->
    <property name="courseList">
        <list>
            <ref bean="course1"></ref>
            <ref bean="course2"></ref>
        </list>
    </property>
    
  2. 把集合註入部分提取出來

    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:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/util/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.atguigu.spring5.collectiontype.Book">
          <property name="list" ref="bookList"></property>
      </bean>
      

FactoryBean

  1. Spring有兩種類型bean,一種普通bean,另一種工廠bean(FactoryBean)
  2. 普通bean:在配置文件中定義bean類型就是返回類型
  3. 工廠bean:在配置文件中定義bean類型可以和返回類型不一樣

第一步,創建類,讓這個類作為工廠bean,實現介面FactoryBean

第二步,實現介面裡面的方法,在實現的方法中定義返回的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;
    }
}

第三步,配置spring配置文件

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

測試類:

public void test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    Course course = context.getBean("mybean", Course.class);
    System.out.println(course);
}

bean作用域

  1. 在Spring裡面,設置創建bean實例可以是單實例,也可以是多實例

  2. 在Spring裡面,預設情況下,bean是單實例對象

    @Test
    public void testCollection2(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");
        Book book =context.getBean("book", Book.class);
        Book book1 =context.getBean("book", Book.class);
        System.out.println(book);  //com.atguigu.sqpring5.collectiontype.Book@5d11346a
        System.out.println(book1);  //com.atguigu.sqpring5.collectiontype.Book@5d11346a
    }
    

    以上例子的兩個輸出是相同的,說明bean預設是單實例對象。

  3. 如何設置單實例or多實例

    1. 在Spring配置文件bean標簽裡面有屬性scope,用於設置單實例還是多實例
    2. scope屬性值
      • singleton:表示單實例對象(預設值)
      • prototype:表示多實例對象
    <!--2 提取list集合類型屬性註入使用-->
    <bean id="myBean" class="com.frx01.spring5.factorybean.MyBean" scope="prototype">
        <property name="list" ref="bookList"></property>
    </bean>
    

    再次測試:

    @Test
    public void testCollection2(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");
        Book book =context.getBean("book", Book.class);
        Book book1 =context.getBean("book", Book.class);
        System.out.println(book);  //com.atguigu.sqpring5.collectiontype.Book@5d11346a
        System.out.println(book1);  //com.atguigu.sqpring5.collectiontype.Book@7a36aefa
    }
    

    以上例子的兩個輸出不同,說明此時bean是多實例對象。

  • singletonprototype區別
    1. singleton表示單實例,prototype表示多實例
    2. 設置scope值singleton時候,載入spring配置文件就會創建一個單實例對象
    3. 設置scope值是prototype時候,不是在載入spring配置文件時候創建對象,在調用getBean方法時候創建多實例對象

bean生命周期

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

  • bean生命周期

    1. 通過構造器創建bean實例(無參構造
    2. 為bean的屬性設置值和對其他bean的引用(調用set方法
    3. 調用bean的初始化的方法(需要進行配置初始化的方法)
    4. bean可以使用了(對象獲取到了
    5. 當容器關閉的時候,調用銷毀bean的方法(需要配置銷毀的方法)
  • 演示bean生命周期

    public class Orders {
    	//無參數構造
        public Orders() {
            System.out.println("第一步 執行無參構造創建bean實例");
        }
    
        //創建set方法設置屬性的值和對其他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("第五步 執行銷毀方法");
        }
    
    }
    

    在Spring配置文件中使用init-method指定初始化方法,用destroy-method指定銷毀方法

    <bean id="orders" class="com.atguigu.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手機"></property>
    </bean>
    

    測試:

    @Test
    public void testCollection4() {
    //        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();
    }
    

    輸出:

    第一步 執行無參構造創建bean實例

    第二步 調用set方法設置屬性的值

    第三步 執行初始化方法

    第四步 獲取創建bean實例對象

    com.atguigu.spring5.bean.Order@192d3247

    第五步 執行銷毀方法

  • bean的後置處理器,bean生命周期有七步

    1. 通過構造器創建bean實例(無參構造
    2. 為bean的屬性設置值和對其他bean的引用(調用set方法
    3. bean實例傳遞到bean後置處理器的方法postProcessBeforeInitialization
    4. 調用bean的初始化的方法(需要進行配置初始化的方法)
    5. bean實例傳遞到bean後置處理器的方法postProcessAfterInitialization
    6. bean可以使用了(對象獲取到了
    7. 當容器關閉的時候,調用銷毀bean的方法(需要配置銷毀的方法)
  • 演示添加後置處理器效果

    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="orders" class="com.atguigu.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
          <property name="oname" value="手機"></property>
      </bean>
      <!--    配置後置處理器-->
      <bean id="MyBeanPost" class="com.atguigu.spring5.bean.MyBeanPost"></bean>
      </beans>
      

      測試:

      @Test
      public void testCollection4() {
      //        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();
      }
      

      輸出:

      第一步 執行無參構造創建bean實例

      第二步 調用set方法設置屬性的值

      在初始化之前執行的方法

      第三步 執行初始化方法

      在初始化之後執行的方法

      第四步 獲取創建bean實例對象

      com.atguigu.spring5.bean.Order@192d3247

      第五步 執行銷毀方法

xml自動裝配

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

  • 實現自動裝配:bean標簽屬性autowire,配置自動裝配
    autowire屬性常用兩個值:
    byName根據屬性名稱註入,註入值bean的id值和類屬性名稱一樣
    byType根據屬性類型註入

  • 演示自動裝配過程

    1. 根據屬性名稱自動註入

      <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>
      
    2. 根據屬性類型自動註入

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

    外部屬性文件

    1. 直接配置資料庫信息

      1. 配置德魯伊連接池

      2. 引入德魯伊連接池依賴jar包(druid)

        <!--直接配置連接池-->
        <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格式文件,寫資料庫信息img

      2. 把外部properties屬性文件引入到spring配置文件

        1. 引入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/util/spring-util.context.xsd">
          
        2. 在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.passwd}"></property>
          </bean>
          

基於註解方式

  • 什麼是註解

    • 註解是代碼特殊標記,格式:@註解名稱(屬性名稱=屬性值,屬性名稱=屬性值)
    • 使用註解,註解作用在上面,方法上面,屬性上面
    • 使用註解目的:簡化xml配置
  • Spring針對Bean管理中創建對象提供註解

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

    以上四個註解功能是一樣的,都可以用來創建bean實例

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

    1. 引入依賴

      img

    2. 開啟組件掃描

      <!--開啟組件掃描
              1 如果掃描多個包 使用逗號隔開
              2 掃描包上層目錄
      -->
      <context:component-scan base-package="com.atguigu"></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-filler,設置掃描哪些內容
      -->
      <context:component-scan base-package="com.atguigu" 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.atguigu">
          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
      
    5. 基於註解方式實現屬性註入

      1. @AutoWired:根據屬性類型自動裝配

        第一步,把service和dao對象創建,在service和dao類添加創建對象註解

        第二步,在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 = "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?

  1. 面向切麵編程(方面),利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合性降低,提高程式的可重用性,同時提高了開發的效率。
  2. 通俗描述:不通過修改源代碼方式,在主幹功能裡面添加新功能
  3. 使用登錄例子說明AOPimg

底層原理

AOP底層使用動態代理

  1. 有介面代理,使用JDK動態代理
    • 創建介面實現類代理對象,增強類的方法img
  2. 沒有介面情況,使用CGLIB動態代理
    • 創建子類的代理對象,增強類的方法img

JDK動態代理

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

    Proxy類是屬於java.lang包中的

    • 調用newProxyInstance方法

      static Object newProxyInstance(ClassLoader loader, 類<?>[] interfaces, InvocationHandler h)

      返回指定介面的代理類的實例,該介面將調用分派給指定的調用處理程式。

      參數:

      ​ 第一個參數:類載入器

      ​ 第二個參數:增強方法所在類,這個類實現的介面,支持多個介面

      ​ 第三個參數:實現這個介面InvocationHandler,創建代理對象,寫增強的部分

  2. 編寫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;
        }
    }
    
    1. 使用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;
          }
      }
      

術語

  • 連接點(Jointpoint):類裡面哪些方法可以被增強,這些方法被稱為連接點。(類中可以被增強的方法

  • 切入點(Pointcut)實際被真正增強的方法

  • 增強(Advice):指的是在目標對象的方法調用前、後或拋出異常時,通過動態代理技術在目標對象的方法周圍插入攔截器的邏輯代碼,從而實現對目標對象方法的增強和定製。

  • 通知(增強)實際增強的邏輯部分。通知定義了增強在何時被調用,並指定了增強的類型。

    通知有多種類型:

    • 前置通知
    • 後置通知
    • 返回增強
    • 環繞通知
    • 異常通知
    • 最終通知
  • 切麵/方面(Aspect)把通知應用到切入點的過程(動作)


AOP操作——準備工作

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

    • AspectJ不是Spring組成部分,獨立AOP框架,一般把AspectJ和Spring框架一起使用,進行AOP操作
  2. 基於AspectJ實現AOP操作

    1. 基於xml配置文件實現
    2. 基於註解方式實現(使用)
  3. 在項目工程裡面引入AOP相關依賴img

  4. 切入點表達式

    1. 作用:知道對哪個類裡面的哪個方法進行增強

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

      舉例1:

      對com.atguigu.dao.BookDao類裡面的add進行增強:execution(* com.atguigu.dao.BookDao.add(..))

      舉例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. 創建增強類(編寫增強邏輯)

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

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

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

        //被增強的類
        @Component
        public class User {
        }
        
        //增強的類
        @Component
        public class UserProxy {
        }
        
      3. 在增強類上面添加註解@Aspect

        //增強的類
        @Component
        @Aspect //生成代理對象
        public class UserProxy {
        }
        
      4. spring配置文件開啟生成代理對象

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

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

      //增強的類
      @Component
      @Aspect //生成代理對象
      public class UserProxy {
          //前置通知
          //@Before註解表示作為前置通知
          @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void before(){
              System.out.println("before.......");
          }
          //後置通知(返回通知)
          @AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void afterReturning(){
              System.out.println("afterReturning.....");
          }
          //最終通知
          @After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void after(){
              System.out.println("after.....");
          }
          //異常通知
          @AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void afterThrowing(){
              System.out.println("afterThrowing.....");
          }
      
          //環繞通知
          @Around(value = "execution(* com.frx01.spring5.aopanno.User.add(..))")
          public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
              System.out.println("環繞之前.......");
              //被增強的方法執行
              proceedingJoinPoint.proceed();
              System.out.println("環繞之後.......");
          }
      }
      
    5. 相同切入點抽取

      //相同切入點抽取
      @Pointcut(value ="execution(* com.atguigu.spring5.aopanno.User.add(..))")
      public void pointdemo(){
      }
      
      //前置通知
      //@Before註解表示作為前置通知
      @Before(value = "pointdemo()")  //可直接使用pointdemo作為value
      public void before(){
          System.out.println("before.......");
      }
      
    6. 有多個增強類多同一個方法進行增強,設置增強類優先順序

      在增強類上面添加註解@Order(數字類型值)數字類型值越小優先順序越高

      @Component
      @Aspect
      @Order(1)
      public class PersonProxy {
      }
      
    7. 完全使用註解開發

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

      @Configuration
      @ComponentScan(basePackages = {"com.atguigu"})
      @EnableAspectJAutoProxy(proxyTargetClass = true)
      public class ConfigAop {
      }
      

AOP操作——AspectJ配置文件

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

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

    <!--創建對象-->
    <bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
    <bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
    
  3. Spring配置文件配置切入點

    <!--配置aop增強-->
    <aop:config>
        <!--切入點-->
        <aop:pointcut id="p" expression="execution(* com.frx01.spring5.aopxml.Book.buy(..))"/>
        <!--配置切麵-->
        <aop:aspect ref="bookProxy">
            <!--配置增強作用在哪個方法上-->
            <aop:before method="before" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>
    


JdbcTemplate

概念和準備

  • 什麼是JdbcTemplate

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

  • 準備工作

    1. 創建資料庫和表

      CREATE DATABASE user_db
      CREATE TABLE t_book(
      	userId BIGINT PRIMARY KEY,
      	username VARCHAR(100) NOT NULL,
      	ustatus VARCHAR(50) NOT NULL)
      
    2. 引入相關的jar包img

    3. Spring配置文件配置資料庫的連接池

      <!-- 資料庫連接池 -->
      <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>
      
    4. 配置JdbcTemplate對象,註入DataSource

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

      配置文件:

      <!--開啟組件掃描-->
      <context:component-scan base-package="com.atguigu"></context:component-scan>
      

      Service類:

      @Service
      public class BookService {
          //註入dao
          @Autowired
          private BookDao bookDao;
      }
      

      Dao類:

      @Repository
      public class BookDaoImpl implements BookDao{
          //註入JdbcTemplate
          @Autowired
          private JdbcTemplate jdbcTemplate;
      }
      

JdbcTemplate操作資料庫

添加

  1. 對應資料庫創建實體類

    public class User {
        private String userId;
        private String username;
        private String ustatus;
    
        public String getUserId() {
            return userId;
        }
    
        public String getUsername() {
            return username;
        }
    
        public String getUstatus() {
            return ustatus;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setUstatus(String ustatus) {
            this.ustatus = ustatus;
        }
    }
    
  2. 編寫ServiceDao

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

    2. 調用JdbcTemplate對象裡面update方法實現添加操作

      update(String sql, Object... args)

      參數:

      String sql:sql語句

      Object... args:可變參數,設置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 values(?,?,?)";
            //2.調用方法實現
            Object[] args={ book.getUserId(), book.getUsername(), book.getUstatus()};
            int update = jdbcTemplate.update(sql,args);
            System.out.println(update);
        }
    }
    
  3. 測試

    @Test
    public void testJdbcTemplate(){
        ApplicationContext context =
            new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        Book book = new Book();
        book.setUserId("1");
        book.setUsername("java");
        book.setUstatus("A");
        bookService.addBook(book);
    }
    

    結果:img

修改和刪除

  1. 修改

    @Override
    public void update(Book book) {
        String sql="update t_book set username=?,ustate=? where userId=?";
        Object[] args={ book.getUsername(), book.getUstatus(), book.getUserId()};
        int update = jdbcTemplate.update(sql,args);
        System.out.println(update>0?"修改成功":"修改失敗");
    }
    
  2. 刪除

    @Override
    public void delete(String id) {
        String sql="delete from t_book where userId=?)";
        int update = jdbcTemplate.update(sql, id);
        System.out.println(update>0?"刪除成功":"刪除失敗");
    }
    

查詢返回某個值

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

  2. 使用JdbcTemplate對象裡面的queryForOcject方法實現查詢操作

    queryForObject(String sql, Class<T> requiredType)

    參數:

    String sql:sql語句

    Class<T> requiredType:返回類型Class

//查詢表記錄數
@Override
public int selectCount(){
    String sql="select count(*) from t_book";
    Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
    return count;
}

查詢返回對象

  1. 場景:查詢圖書詳情

  2. JdbcTemplate實現查詢返回對象的方法:queryForObject

    queryForObject(String sql, RowMapper<T> rowMapper, Object... args)

    參數:

    String sql:sql語句

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

    Object... args:sql語句值

 //查詢返回對象
@Override
public Book findBookInfo(String id) {
    String sql="select * from t_book where userId=?";
    //調用方法
    Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class),id);
    return book;
}

查詢返回集合

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

  2. 調用JdbcTemplatequery方法實現查詢返回集合

    query(String sql, RowMapper<T> rowMapper, Object... args)

    參數:

    String sql:sql語句

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

    Object... args: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;
}

批量操作

  1. 批量操作:操作表裡面的多條記錄

  2. JdbcTemplate實現批量添加操作

    batchUpdate(String sql, List<Object[]> batchArgs)

    參數:

    String sql:sql語句

    List<Object[]> batchArgs:List集合,添加多條記錄數據

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

    測試:

    //批量添加_測試
    List<Object[]> batchArgs=new ArrayList<>();
    Object[] o1={"3","java","a"};
    Object[] o2={"4","c++","b"};
    Object[] o3={"5","MySQL","e"};
    batchArgs.add(o1);
    batchArgs.add(o2);
    batchArgs.add(o3);
    //調用批量添加
    bookService.batchAdd(batchArgs);
    
  3. JdbcTemplate實現批量修改操作

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

    測試:

    //批量修改_測試
    List<Object[]> batchArgs=new ArrayList<>();
    Object[] obj1={"java111","a3","3"};
    Object[] obj2={"c++1010","b4","4"};
    Object[] obj3={"MySQL11","c5","5"};
    batchArgs.add(obj1);
    batchArgs.add(obj2);
    batchArgs.add(obj3);
    //調用方法
    bookService.batchUpdate(batchArgs);
    
  4. JdbcTemplate實現批量刪除操作

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

    測試:

    //批量修改
    List<Object[]> batchArgs=new ArrayList<>();
    Object[] obj1={"3"};
    Object[] obj2={"4"};
    batchArgs.add(obj1);
    batchArgs.add(obj2);
    //調用方法實現批量刪除
    bookService.batchDelete(batchArgs);
    


事務管理

概念

  • 什麼是事務?

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

    1. 典型場景:銀行轉賬
    • lucy轉賬100元給mary
    • lucy少100,mary多100
  • 事務的四個特性(ACID

    • 原子性
    • 一致性
    • 隔離性
    • 持久性

搭建事務操作環境

img

  1. 創建資料庫表,添加數據

    CREATE TABLE t_account(
    	id VARCHAR(20),
    	username VARCHAR(50),
    	money VARCHAR(50))
    INSERT INTO t_account VALUES('1','lucy',1000)
    INSERT INTO t_account VALUES('2','mary',1000)
    
  2. 創建service,搭建dao,完成對象創建註入關係

    service註入dao,在dao註入JdbcTemplate,在JdbcTemplate註入DataSource

    @Service
    public class UserService {
        //註入dao
        @Autowired
        private UserDao userDao;
    }
    
    @Repository
    public class UserDaoImpl implements UserDao{
        @Autowired
        private JdbcTemplate jdbcTemplate;
    }
    
  3. dao創建兩個方法,多錢和少錢的方法,在service創建方法(轉賬的方法)

    @Repository
    public class UserDaoImpl implements UserDao{
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        //少錢
        @Override
        public void reduceMoney() {
            String sql="update t_account set money=money-? where username=?";
            jdbcTemplate.update(sql,100,"lucy");
        }
    
        //多錢
        @Override
        public void addMoney() {
            String sql="update t_account set money=money+? where username=?";
            jdbcTemplate.update(sql,100,"mary");
        }
    }
    
    @Service
    public class UserService {
        //註入dao
        @Autowired
        private UserDao userDao;
    
        //轉賬的方法
        public  void  accountMoney(){
            //lucy少100
            userDao.reduceMoney();
            
            //mary多100
            userDao.addMoney();
        }
    }
    
  4. 上面代碼,如果正常執行沒有問題的,但是如果代碼執行過程中出現異常,有問題

    //轉賬的方法
    public  void  accountMoney(){
        //lucy少100
        userDao.reduceMoney();
    
        //模擬異常
        int i =10/0;
    
        //mary多100
        userDao.addMoney();
    }
    //結果lucy少了100,而mary並沒有增加100
    
    • 以上的問題如何解決呢?

      • 使用事務進行解決
    • 事務操作過程

      //轉賬的方法
      public  void  accountMoney(){
          try {
              //第一步 開啟事務
      
              //第二步 進行業務操作
              //lucy少100
              userDao.reduceMoney();
      
              //模擬異常
              int i = 10 / 0;
      
              //mary多100
              userDao.addMoney();
              
              //第三步 沒有發生異常,提交事務
          }catch (Exception e){
              //第四步 出現異常,事務回滾
          }
      }
      

Spring事務管理介紹

  1. 事務添加到JavaEE三層結構裡面Service層(業務邏輯層)

  2. 在Spring進行事務管理操作有兩種方式:編程式事務管理聲明式事務管理(使用)

  3. 聲明式事務管理

    1. 基於註解方式(使用)
    2. 基於xml配置文件方式
  4. 在Spring進行聲明式事務管理,底層使用AOP原理

  5. Spring事務管理API:PlatformTransactionManager

    PlatformTransactionManager介面,代表事務管理器,這個介面針對不同的框架提供不同的實現類img


註解聲明式事務管理

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

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

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

      <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"
             xmlns:tx="http://www.springframework.org/schema/tx"
             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
                                  http://www.springframework.org/schema/tx http://www.sp
      
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 哈嘍大家好,我是鹹魚 想必大家都聽說過 Instagram ,它是全球最受歡迎的社交媒體平臺之一,擁有數十億的活躍用戶 Instagram 誕生於 2010 年,上線一周就坐擁 10 萬註冊用戶,一年之內就擁有了 1400 萬用戶,可見擴張趨勢突飛猛進。 Instagram 誕生的時候只有 3 個工 ...
  • 本節介紹Util應用框架如何進行驗證. 概述 驗證是業務健壯性的基礎. .Net 提供了一套稱為 DataAnnotations 數據註解的方法,可以對屬性進行一些基本驗證,比如必填項驗證,長度驗證等. Util應用框架使用標準的數據註解作為基礎驗證,並對自定義驗證進行擴展. 基礎用法 引用Nuge ...
  • 本文介紹了結構型設計模式中的橋接模式,講解了它的特點和相關構成,並通過相應的案例,使用Java代碼進行演示。 ...
  • 本節介紹Util應用框架對AspectCore AOP的使用. 概述 有些問題需要在系統中全局處理,比如記錄異常錯誤日誌. 如果在每個出現問題的地方進行處理,不僅費力,還可能產生大量冗餘代碼,並打斷業務邏輯的編寫. 這類跨多個業務模塊的非功能需求,被稱為橫切關註點. 我們需要把橫切關註點集中管理起來 ...
  • 1. HashMap和HashT able的區別 HashMap和Hashtable是兩種常見的哈希表數據結構,它們在實現上有一些區別。 線程安全性:Hashtable是線程安全的,而HashMap不是。Hashtable的方法都是同步的,可以在多線程環境中使用,但這樣會造成一定的性能開銷。Hash ...
  • kubelet 簡介 kubernetes 分為控制面和數據面,kubelet 就是數據面最主要的組件,在每個節點上啟動,主要負責容器的創建、啟停、監控、日誌收集等工作。它是一個在每個集群節點上運行的代理,負責確保節點上的容器根據PodSpec(Pod定義文件)正確運行。 Kubelet執行以下幾項 ...
  • 機器學習是通過研究數據和統計信息使電腦學習的過程。機器學習是邁向人工智慧(AI)的一步。機器學習是一個分析數據並學會預測結果的程式。 數據集 在電腦的思維中,數據集是任何數據的集合。它可以是從數組到完整資料庫的任何東西。 數組的示例: [99,86,87,88,111,86,103,87,94, ...
  • @目錄山茶花100ptsT1區間逆序對60pts100pts 區間操作固定套路,轉化為首碼操作dream20pts 神奇分塊杭州:轉化題意,正難則反正難則反(或者對於這種有刪邊操作的題), 我們看成反向加邊看題:構造坐飛機:斜率優化DP抓頹 : 啟髮式合併 + stl大雜燴討厭的線段樹Foo Fig ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...