Spring 5

来源:https://www.cnblogs.com/DFshmily/archive/2022/10/02/16735412.html
-Advertisement-
Play Games

Spring 5框架 一、Spring概念 1、Spring是輕量級的JavaEE框架 2、Spring可以解決企業應用開發的複雜性 3、Spring有兩個核心部分:IOC和AOP ​ 1)IOC:控制反轉,把創建對象過程交給Spring進行管理 ​ 2)AOP:面向切麵,不修改源代碼進行功能增強 ...


Spring 5框架

一、Spring概念

1、Spring是輕量級的JavaEE框架

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

3、Spring有兩個核心部分:IOC和AOP

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

​ 2)AOP:面向切麵,不修改源代碼進行功能增強

4、Spring特點

  1. 方便解耦,簡化開發
  2. AOP編程的支持
  3. 方便程式的測試
  4. 方便集成各種優秀框架(方便整合其他框架)
  5. 方便進行事務操作
  6. 降低API開發難度

入門案例:

1.下載地址:https://repo.spring.io/ui/native/release/org/springframework/spring

2.打開idea,新建java項目(項目例子文件:Java/Spring at main · DFshmily/Java (github.com))

3.導入Spring5相關jar包

image

image

4.創建普通類,在這個類創建普通方法

public class User{
    public void add(){
        System.out.println("add......");
    }
}

5.創建Spring配置文件,在配置文件創建對象

Spring配置文件使用xml格式,創建在src下

image

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

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

6.進行代碼測試編寫

User.java

package com.spring;

public class User {
    public void add(){
        System.out.println("add......");
    }
}

TestSpring.java

package com.spring.testdemo;

import com.spring.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring {
    @Test
    public void testAdd(){
        //1.載入spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2.獲取配置創建的對象
        User user = context.getBean("user",User.class);
        System.out.println(user);
        user.add();
    }

}
運行結果:
com.spring.User@506ae4d4
add......

二、IOC框架

1.IOC底層原理

(1)什麼是IOC

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

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

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

(2)原理

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

image

image

IOC過程:

  1. 第一步xml配置文件,配置創建的對象
 <bean id="user" class="com.spring.User"></bean>
  1. 有service類和dao類,創建工廠類

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

2.IOC介面(BeanFactory)

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

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

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

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

​ 2)ApplicationContext:BeanFactory介面的子介面,提供更多更強大的功能,一般由開發人員進行使用

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

(3)ApplicationContext介面實現類

image

3.IOC操作Bean管理(基於xml方式)

(1)什麼是Bean管理

​ 1)Spring創建對象

​ 2)Spring註入屬性

(2)Bean管理操作有兩種方式

​ 1)基於xml配置文件方式實現

​ 2)基於註解方式實現

(3)基於xml方式創建對象

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

​ 1)在spring配置文件中,使用bean標簽,標簽裡面添加對應屬性,就可以實現對象創建

​ 2)在bean標簽有很多屬性,介紹常用的屬性

id屬性:唯一標識
class屬性:類全路徑(包類路徑)

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

(4)基於xml方式註入屬性

​ 1)DI:依賴註入,就是註入屬性

​ ⭐第一種註入方式:使用set方法註入

package com.spring;

public class Book {
    private String bname;

    public void setBname(String bname) {
        this.bname = bname;
    }
}

xml:

  <!--set方法註入屬性-->
    <bean id="book" class="com.spring.Book">
        <!--使用property完成屬性註入
        name:類裡面屬性名稱
        value:向屬性註入的值-->
    <property name="bname" value="shmily"></property>
    </bean>

Test:

public class TestSpring {
    @Test
    public void OrdersTest(){
        //1.載入spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2.獲取配置創建的對象
        Book book = context.getBean("book",Book.class);
        System.out.println(book);
        book.toString();
    }
}
運行結果:
    Book{bname='shmily'}

​ ⭐第二種註入方式:使用有參構造進行註入:

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

    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.spring.Orders">
        <constructor-arg name="oname" value="PC"></constructor-arg>
        <constructor-arg name="address" value="china"></constructor-arg>
        還有個索引註入 <constructor-arg index="0" value="china"></constructor-arg>,"0"是下標
    </bean>

​ Test:

public class TestSpring {
    @Test
    public void OrdersTest(){
        //1.載入spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2.獲取配置創建的對象
        Orders orders = context.getBean("orders",Orders.class);
        System.out.println(orders);
        orders.toString();
    }
}

運行結果:
    Orders{oname='PC', address='china'}

第三種:p名稱空間註入

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

​ ①添加p名稱空間在配置文件中:

    xmlns:p="http://www.springframework.org/schema/p"

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

    <bean id="book" class="com.spring.Book" p:bname="書"></bean>

4.IOC操作Bean管理(xml其他類型屬性)

(1)字面量

​ 1)null值

<!--null值-->
     <property name="address">
    <null/>
    </property>

​ 2)屬性值包含特殊符號

<!--屬性值包含特殊符號
    1.把<>進行轉義
    2.把帶特殊符號內容寫到CDATA
    -->
     <property name="address">
    	<value><![CDATA[<<南京>>]]</value>
        </property>

(2)註入屬性--外部bean

​ 1)創建兩個類service類和dao類

​ 2)在service調用dao裡面的方法

public class UserService {
    public void add(){
        System.out.println("service add......");
    }

    //原始方式:創建UserDao對象
    /*UserDao userDao = new UserDaoImpl();
            userDao.update();*/

    //創建UserDao類型屬性,生成set方法
    private UserDao userDao;

    public void setUserDao(UserDaoImpl userDao) {
        this.userDao = userDao;
    }
}

​ 3)在spring配置文件進行配置

<!--    1.service和dao對象創建-->
    <bean id="userService" class="com.spring.service.UserService">
    <!--註入userDao對象
        name屬性:類裡面屬性名稱
        ref屬性:創建userDao對象bean標簽id值
        -->
    <property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <bean id="userDaoImpl" class="com.spring.dao.UserDaoImpl"></bean>
 @Test
    public void testAdd(){
        //1.載入spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        //2.獲取配置創建的對象
        UserService userService = context.getBean("userService",UserService.class);
        userService.add();
    }

(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.spring.bean.Emp">
        <!--設置兩個普通屬性-->
        <property name="ename" value="shmily"></property>
        <property name="gender" value="男"></property>
        <!--設置對象類型屬性-->
        <property name="dept">
            <bean id="dept" class="com.spring.bean.Dept">
                <property name="dname" value="部門"></property>
            </bean>
        </property>
    </bean>

4)註入屬性--級聯賦值

  1. 第一種:
<!--級聯賦值-->
    <bean id="emp" class="com.spring.bean.Emp">
    <!--設置兩個普通屬性-->
    <property name="ename" value="shmily"></property>
    <property name="gender" value="男"></property>
        
        <!--級聯賦值-->
        <property name="dept" ref="dept"></property>
    </bean>
    <bean id="dept" class="com.spring.bean.Dept">
        <property name="dname" value="部門"></property>
    </bean>
  1. 第二種:
  <!--級聯賦值-->
    <bean id="emp" class="com.spring.bean.Emp">
    <!--設置兩個普通屬性-->
    <property name="ename" value="shmily"></property>
    <property name="gender" value="男"></property>
        
        <!--級聯賦值,用dept.dname時要生成get方法-->
        <property name="dept" ref="dept"></property>
        <property name="dept.dname" value="部門"></property>
    </bean>
    <bean id="dept" class="com.spring.bean.Dept">
        <property name="dname" value="部門"></property>
    </bean>

5.IOC操作Bean管理(xml註入集合屬性)

(1)註入數組類型屬性

(2)註入List集合類型屬性

(3)註入Map集合類型屬性

​ 1)創建類,定義數組、list、map、set類型屬性,生成對應set方法

package com.spring;

import java.util.List;
import java.util.Map;
import java.util.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;
    }
}

​ 2)在spring配置文件配置

    <!--集合類型屬性註入-->
    <bean id="stu" class="com.spring.Stu">
        <!--數組類型屬性註入-->
        <property name="courses">
            <array>
                <value>java課程</value>
                <value>MySQL</value>
            </array>
        </property>
<!--        或者:list屬性註入-->
        <property name="list">
            <list>
                <value>D</value>
                <value>F</value>
            </list>
        </property>
<!--        map類型屬性註入-->
        <property name="maps">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="C" value="c"></entry>
            </map>
        </property>
<!--        set類型屬性註入-->
        <property name="sets">
            <set>
                <value>MySQL</value>
                <value>Redis</value>
            </set>
        </property>
    </bean>

Test:

package testdemo;

import com.spring.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StuTest {
    @Test
    public void testCollection(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Stu stu = context.getBean("stu",Stu.class);
        stu.test();
    }
}
運行結果:
[java課程, MySQL]
[D, F]
{JAVA=java, C=c}

(4)在集合裡面這種對象類型值

       <!--創建多個course對象-->
        <bean id="course1" class="com.spring.Course">
            <property name="cname" value="名字1"></property>
        </bean>
    <bean id="course2" class="com.spring.Course">
        <property name="cname" value="名字2"></property>
    </bean>
        <!--        註入list集合類型,值是對象-->
        <property name="courseList">
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>
    </bean>

(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: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>java</value>
        <value>C</value>
    </util:list>
<!--    2.提取list集合類型屬性註入使用-->
    <bean id="book" class="com.spring.Book">
        <property name="list" ref="bookList"></property>
    </bean>

6.IOC操作Bean管理(FactoryBean)

(1)Spring有兩種類型bean:一種普通bean,另一種工廠bean(FactoryBean)

(2)普通bean:在配置文件中定義bean類型就是返回類型

(3)工廠bean:在配置文件定義bean類型可以和返回類型不一樣

​ 1)第一步 創建類,讓這個類作為工廠bean,實習介面FactoryBean

​ 2)第二步 實現介面裡面的方法,在實現的方法中定義返回的bean類型

MyBean.java

package com.factorybean;

import com.spring.Course;
import org.springframework.beans.factory.FactoryBean;

public class MyBean implements FactoryBean<Course> {
    //定義返回bean
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("dzq");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

Test:

package testdemo;

import com.spring.Course;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class factorybeanTest {
    @Test
    public void testCollection1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);
    }
}

配置文件:

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

    </bean>

7.IOC操作Bean管理(bean作用域)

(1)在Spring裡面,設置創建bean實例時單實例還是多實例

(2)在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);
        System.out.println(book1);
        System.out.println(book2);
    }

運行結果:
com.spring.Book@6cb107fd
com.spring.Book@6cb107fd
    
 因為book1和book2的地址相同,所以他們是單實例對象

(3)如何設置單實例還是多實例

​ 1)在spring配置文件bean標簽裡面有屬性(scope)用於設置單實例還是多實例

​ 2)scope屬性值

第一個值 預設值:singleton,表示單實例對象

第二個值 prototype,表示多實例對象

 <bean id="book" class="com.spring.Book" scope="prototype">
        <property name="list" ref="bookList"></property>
    </bean>
運行結果:
com.spring.Book@710636b0
com.spring.Book@3de8f619
   
 它們地址不同,現在是多實例對象  
 

​ 3)singleton和prototype區別

​ 1.singleton單實例,prototype多實例

​ 2.設置scope值是singleton時候,載入spring配置文件的時候就會創建單實例對象

​ 設置scope值是prototype時候,不是在載入spring配置文件時候創建對象,在調用getBean方法時候創建多實例對象

​ 瞭解:request:每一次HTTP請求都會創建一個新的bean實例,該bean僅在當前HTTP request內有效,在請求完成後,bean會失效並被垃圾回收器回收。

​ session:每一次HTTP請求都會創建一個新的bean,該bean僅在當前HTTP session內有效。同一個session會話共用一個實例,不同的會話使用不同的實例。

8.IOC操作Bean管理(bena生命周期)

(1)生命周期

​ 1)從對象創建到對象銷毀的過程

(2)bean生命周期

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

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

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

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

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

(3)演示bean的生命周期

例子:

package com.bean;

public class Orders {


    private String oname;

    @Override
    public String toString() {
        return "Orders{" +
                "oname='" + oname + '\'' +
                '}';
    }

    //1.無參構造
    public Orders() {
        System.out.println("第一步 執行無參數構造創建bean實例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步 調用set方法設置屬性值");
    }

    //創建執行的初始化的方法
    private void initMethod(){
        System.out.println("第三步 執行初始化的方法");
    }

    //創建執行的銷毀的方法
    public void destroyMethod(){
        System.out.println("第五步 執行銷毀的方法");
    }
}


配置文件:

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

Test:

public class OrdersTest {
    @Test
    public void orderTset(){
//        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實例對象
Orders{oname='手機'}
第五步 執行銷毀的方法

(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,創建後置處理器

MyBeanPost.java

package com.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.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;
    }
}


Orders.java

package com.bean;

public class Orders {


    private String oname;

    @Override
    public String toString() {
        return "Orders{" +
                "oname='" + oname + '\'' +
                '}';
    }

    //1.無參構造
    public Orders() {
        System.out.println("第一步 執行無參數構造創建bean實例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步 調用set方法設置屬性值");
    }

    //創建執行的初始化的方法
    private void initMethod(){
        System.out.println("第四步 執行初始化的方法");
    }

    //創建執行的銷毀的方法
    public void destroyMethod(){
        System.out.println("第七步 執行銷毀的方法");
    }
}

配置文件:

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

<!--    配置後置處理器-->
    <bean id="myBeanPost" class="com.bean.MyBeanPost"></bean>

Test:

package testdemo;

import com.bean.Orders;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class OrdersTest {
    @Test
    public void orderTset(){
//        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實例對象
Orders{oname='手機'}
第七步 執行銷毀的方法

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

(1)什麼是自動裝配

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

(2)演示自動裝配過程

​ 1)根據屬性名稱自動註入

配置:

<!--手動裝配-->
<!--    <bean id="emp" class="com.autowire.Emp">-->
<!--        <property name="dept" ref="dept"></property>-->
<!--    </bean>-->
<!--    <bean id="dept" class="com.autowire.Dept"></bean>-->

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

    

Emp.java

package com.autowire;
//員工
public class Emp {

    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
    public void test(){
        System.out.println(dept);
    }
}

Dept.java

package com.autowire;
//部門
public class Dept {
    @Override
    public String toString() {
        return "Dept{}";
    }
}

Test:

public class TestSpring {
    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
        Emp emp = context.getBean("emp",Emp.class);
        System.out.println(emp);
    }
}


運行結果:
 Emp{dept=Dept{}}

​ 2)根據屬性類型自動註入

 <bean id="emp" class="com.autowire.Emp" autowire="byType">
    </bean>
    <bean id="dept" class="com.autowire.Dept"></bean>

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

(1)直接配置資料庫信息

​ 1)配置Druid(德魯伊)連接池

​ 2)引入Druid連接池jar包(下載地址:[Central Repository: com/alibaba/druid (maven.org)](https://druid.apache.org/downloads.html))

​ 配置文件:

<!--    直接配置連接池-->
    <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/book"></property>
        <property name="username" value="root"></property>
        <property name="password" value=""></property>
    </bean>

(2)引入外部屬性文件配置資料庫連接池

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

prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/book
prop.username=root
prop.password=""

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

​ ⚫引入context命名空間

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 			  http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

​ ⚫在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>

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

(1)什麼是註解

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

​ 2)使用註解,註解可以作用在類、方法、屬性上面

​ 3)使用註解目的:簡化xml配置

(2)Spring針對Bean管理創建對象提供註解

​ 1)@Component

​ 2)@Service

​ 3)@Controller

​ 4)@Repository

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

(3)基於註解方式實現對象創建

​ 1)引入依賴:spring-aop-5.3.9.jar

​ 2)開啟組件掃描

<!--    開啟組件掃描
          如果掃描多個包,多個包用逗號隔開或者掃描包上層目錄
-->
    <context:component-scan base-package="com"></context:component-scan>

​ 3)創建類,在類上面添加對象註解

package com.service;

import org.springframework.stereotype.Component;

/*
在註解裡面value屬性值可以省略不寫
預設值是類名稱,首字母小寫
UserService-->userService
@Component可以替代為@Service,@Controller,@Repository,但在此一般習慣於用@Component
 */
@Component(value = "userService")//<bean id="userService" class=""/>
public class UserService {

    public void add(){
        System.out.println("service add...");
    }
}


(4)開啟組件掃描細節配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!--    開啟組件掃描
          如果掃描多個包,多個包用逗號隔開或者掃描包上層目錄
-->
    <context:component-scan base-package="com"></context:component-scan>

    
<!--    實例1:use-default-filters="false" 表示現在不使用預設filter,自己配置filter
             context:include-filter 表示掃描哪些內容
-->
    <context:component-scan base-package="com" 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">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>

(5)基於註解方式實現屬性註入

​ 1)@AutoWired :根據屬性類型進行自動裝配

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

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

UserService.java

package com.service;

import com.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    //定義dao類型屬性,不需要添加set方法,添加註入屬性註解
    @Autowired //根據類型進行註入
    private UserDao userDao;

    public void add(){
        System.out.println("service add...");
        userDao.add();
    }
}

UserDao.java

package com.dao;

public interface UserDao {
    public void add();
}

UserDaoImpl.java

package com.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao{
    @Override
    public void add(){
        System.out.println("dao add...");
    }
}

Test:

    @Test
    public void userTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml");
        UserService userService=context.getBean("userService", UserService.class);
        userService.add();
    }
}
運行結果;
service add...
dao add...

​ 2)@Qualifier:根據屬性名稱進行註入

​ @Qualifier註解的使用,和@AutoWired一起使用

UserService.java

@Service
public class UserService {

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

    public void add(){
        System.out.println("service add...");
        userDao.add();
    }
}

UserDaoImpl.java

@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao{
    @Override
    public void add(){
        System.out.println("dao add...");
    }
}

​ 3)@Resource:可以根據類型註入,也可以根據名稱註入

  @Service
public class UserService {
	//@Resource()  //根據類型進行註入
    @Resource(name = "userDaoImpl1") //根據名稱進行註入
    private UserDao userDao;

    public void add(){
        System.out.println("service add...");
        userDao.add();
    }
}

​ 4)@Value:註入普通類型屬性

  @Value(value = "DF")
    private String name;

(6)完全註解開發

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

SpringConfig.java

package com.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration //作為配置類,替代xml配置文件
@ComponentScan(basePackages = {"com"})
public class SpringConfig {

}

​ 2)編寫測試類

package com.testdemo;

import com.config.SpringConfig;
import com.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestSpring {
    @Test
    public void userTest(){
        //載入配置類
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService=context.getBean("userService", UserService.class);
        userService.add();
    }
}


三、AOP

1.概念

(1)什麼是AOP

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

​ 2)通俗描述:不通用修改源代碼方式,在主幹功能里添加新功能

​ 3)使用登錄例子說明AOP

image

### 2.AOP(底層原理)

(1)AOP底層使用動態代理

​ 1)有兩種情況動態代理

​ ①有介面情況,使用JDK動態代理

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

image

​ ②沒有介面情況,使用CGLTB動態代理

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

image

3.AOP(JDK動態代理)

(1)使用JDK動態代理,使用proxy類裡面的方法創建代理對象

java.lang.reflect 
Class Proxy
java.lang.Object 
java.lang.reflect.Proxy 

​ 1)調用newProxyInstance方法

 static Object    newProxyInstance(ClassLoader loader, 類<?>[] interfaces, InvocationHandler h)  
    			  返回指定的介面,將方法調用指定的調用處理程式的代理類的一個實例。 

​ 方法中的三個參數:

ClassLoader loader 類載入器
類<?>[] interfaces 增強方法所在的類,這個類實現的介面,支持多個介面
InvocationHandler h 實現這個介面InvocationHandler,創建代理對象,寫增強的方法

(2)編寫JDK動態代碼

​ 1)創建介面,定義方法

UserDao.java

package com.spring;

public interface UserDao {
   public int add(int a,int b);
   public String update(String id);
}

​ 2)創建介面實現類,實現方法

UserDaoImpl.java

package com.spring;

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類創建介面代理對象

JDKProxy.java

package com.spring;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

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;
//            }
//        });
        //第二種:自定義名稱UserDaoProxy創建代理對象代碼
        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);
   }
}
//第二種:自定義名稱UserDaoProxy創建代理對象代碼
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;
    }
}


運行結果:
在方法之前執行...add:傳遞的參數:[1, 2]
add方法執行了...
在方法之後執行...com.spring.UserDaoImpl@7ca48474
result:3

4.AOP(術語)

(1)連接點

​ 類裡面哪些方法可以被增強,這些方法稱為連接點

(2)切入點

​ 實際被真正增強的方法,稱為切入點

(3)通知(增強)

​ 1)實際增強的邏輯部分稱為通知(增強)

​ 2)通知有多種類型

​ ①前置通知

​ ②後置通知

​ ③環繞通知

​ ④異常通知

​ ⑤最終通知 finally

(4)切麵

​ 是動作,把通知應用到切入點的過程

5.AOP(準備)

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

​ 1)什麼是AspectJ

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

(2)基於AspectJ實現AOP操作

​ 1)基於xml配置文件

​ 2)基於註解方式實現(使用)

(3)在項目工程裡面引入AOP相關依賴

image

(4)切入點表達式

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

​ 2)語法結構:

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

舉例1:對com.spring.UserDao類裡面的add進行增強

​ execution(* com.spring.UserDao.add(...))

舉例2:對com.spring.UserDao類裡面的所有方法進行增強

​ execution(* com.spring.UserDao.*(...))

舉例3:對com.spring包裡面所有類,類裡面的所有方法進行增強

​ execution(* com.spring.*.*(...))

6.AOP操作(AspectJ註解)

(1)創建類,在類裡面定義方法

User.java

package com.aop;

public class User {
    public void add(){
        System.out.println("add...");
    }
}

(2)創建增強類(編寫增強邏輯)

(1)在增強類中創建方法,讓不同方法代表不同通知類型

UserProxy.java

package com.aop;
//增強的類
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 https://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd ">
    
<!--    開啟註解掃描-->
    <context:component-scan base-package="com.aop"></context:component-scan>
</beans>

​ 2)使用註解創建User和UserProxy對象

User.java

//被增強的類
@Component
public class User {
    public void add(){
        System.out.println("add...");
    }
}

UserProxy.java

//增強的類
@Component
public class UserProxy {

    //前置通知
    public void before(){
        System.out.println("before...");
    }
}

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

UserProxy.java

//增強的類
@Component
@Aspect //生成代理對象
public class UserProxy {

    //前置通知
    public void before(){
        System.out.println("before...");
    }
}

​ 4)在spring配置文件中開啟生成代理對象

xml:

<!--    開啟aspect生成代理對象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

(4)配置不同類型的通知

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

UserProxy.java

package com.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//增強的類
@Component
@Aspect //生成代理對象
public class UserProxy {

    //前置通知
    //@Before註解表示作為前置通知
    @Before(value = "execution(* com.aop.User.add(..))")
    public void before(){
        System.out.println("before...");
    }

    //最終通知
    @After(value = "execution(* com.aop.User.add(..))")
    public void after(){
        System.out.println("after...");
    }


    //後置通知(返回通知)
    @AfterReturning(value = "execution(* com.aop.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning...");
    }


    //異常通知
    @AfterThrowing (value = "execution(* com.aop.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing...");
    }

    //環繞通知
    @Around(value = "execution(* com.aop.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("環繞之前...");

        //被增強的方法執行
        proceedingJoinPoint.proceed();

        System.out.println("環繞之後...");
    }
}



Test:

package com.testdemo;

import com.aop.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    @Test
    public void testAop(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();
    }
}

運行結果:
    
環繞之前...
before...
add...
afterReturning...
after...
環繞之後...

(5)相同的切入點抽取

    //相同切入點抽取
    @Pointcut(value = "execution(* com.aop.User.add(..))")
    public void pointcut(){
    }

    //前置通知
    //@Before註解表示作為前置通知
    @Before(value = "pointcut")
    public void before(){
        System.out.println("before...");
    }

(6)有多個增強類多個同一方法進行增強,設置增強類優先順序

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

@Component
@Aspect
@Order(1)
public class PersonProxy {

    @Before(value = "execution(* com.aop.User.add(..))")
    public void afterReturning(){
        System.out.println("Person Before...");
    }
}

(7)完全使用註解開發

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

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

}

7.AOP操作(AspectJ配置文件)

(1)創建兩個類,增強類和被增強類,創建方法

Book.java

package com.aopxml;
//被增強類
public class Book {
    public void buy(){
        System.out.println("buy...");
    }
}

BookProxy.java

package com.aopxml;
//增強類
public class BookProxy {
    public void before(){
        System.out.println("before...");
    }
}

(2)在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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--    創建對象-->
    <bean id="book" class="com.aopxml.Book"></bean>
    <bean id="bookProxy" class="com.aopxml.BookProxy"></bean>
</beans>

(3)在spring配置文件中配置切入點

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

Test:

    @Test
    public void testAop1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book = context.getBean("book", Book.class);
        book.buy();
    }

運行結果:
    
before...
buy...

四、JdbcTemplate

1.什麼是JdbcTemplate

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

2.準備工作

(1)引入相關jar包

image

(2)在spring配置文件中配置資料庫連接池

<!--    資料庫連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/book"></property>
        <property name="username" value="root"></property>
        <property name="password" value=""></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    </bean>

(3)配置JdbcTemplate對象,註入DataSource

<!--    JdbcTemplate對象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--        註入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

(4)創建sercvice類,創建dao類,在dao註入jdbcTemplate對象

​ ⚫配置文件

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

​ ⚫service

package com.service;

import com.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookService {

    //註入dao
    @Autowired
    private BookDao bookDao;
}

⚫Dao

package com.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class BookDaoImpl implements BookDao{

    //註入JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;

}

3.JdbcTemplate操作資料庫(添加)

(1)對應資料庫表創建實體類

User.java

package com.entity;

public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;

    public Integer getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public String getEmail() {
        return email;
    }
}

(2)編寫service和dao

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

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

update(String sql,Object...args)

有兩個參數:

⚫第一個參數:sql語句

⚫第二個參數:可變參數,設置sql語句值

BookDaoImpl.java

package com.dao;

import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;


@Repository
public class BookDaoImpl implements BookDao{

    //註入JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;

    //添加的方法
    @Override
    public void add(Book book) {
        //1.創建sql語句
        String sql = "insert into t_user values(?,?,?)";
        //2.調用方法實現
       int update = jdbcTemplate.update(sql,book.getId(),book.getUsername(),book.getPassword(),book.getEmail());
        System.out.println(update);
    }
}

BookService.java

package com.service;

import com.dao.BookDao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;



@Service
public class BookService {

    //註入dao
    @Autowired
    private BookDao bookDao;

    //添加的方法
    public void addBook(Book book){
        bookDao.add(book);
    }

}

BookDao.java

package com.dao;


import com.entity.Book;

public interface BookDao {
    //添加的方法
    void add(Book book);
}

Book.java

package com.entity;

public class Book {
    private String id;
    private String username;
    private String password;
    private String email;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public String getEmail() {
        return email;
    }
}

(3)測試類

package com.test;

import com.entity.Book;
import com.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TsetBook {

    @Test
    public void testJdbcTemplate(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService",BookService.class);
        Book book = new Book();
        book.setId("7");
        book.setUsername("c");
        book.setPassword("c");
        book.setEmail("[email protected]");
        bookService.addBook(book);
    }
}

運行結果:
10月 02, 2022 7:44:51 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
1

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

BookService.java

package com.service;

import com.dao.BookDao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;



@Service
public class BookService {

    //註入dao
    @Autowired
    private BookDao bookDao;

    //添加的方法
    public void addBook(Book book){
        bookDao.add(book);
    }


    //修改的方法
    public void updateBook(Book book){
        bookDao.update(book);
    }

    //刪除的方法
    public void deleteBook(String id){
        bookDao.delete(id);
    }
}

BookDao.java

package com.dao;


import com.entity.Book;

public interface BookDao {
    //添加的方法
    void add(Book book);

    void update(Book book);

    void delete(String id);


}

BookDaoImpl.java

package com.dao;

import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;


@Repository
public class BookDaoImpl implements BookDao{

    //註入JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;

    //添加的方法
    @Override
    public void add(Book book) {
        //1.創建sql語句
        String sql = "insert 

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

-Advertisement-
Play Games
更多相關文章
  • 簡述 類型:創建型 目的:實現對客戶端中對象族的平替。 對象族 一組對象。比如,華為的手機,筆記本,平板可以統稱為華為族。 我們藉以下案例來說說如何使用抽象工廠模式平替對象族。 優化案例 最初版 public interface Uploader { void upload(String fileN ...
  • 一 引入 項目有個新需求,當點擊或觸碰TextBox時,基於TextBox的相對位置,彈出一個自定義的Keyboard,如下圖所示: 二 KeyboardControl 先實現一個自定義的KeyboardControl,它繼承自Window。 Xaml代碼如下: <Window x:Class="W ...
  • 我們在創建條形碼時,如果以圖片的方式將創建好的條碼保存到指定文件夾路徑,可以在程式中直接載入圖片使用;已生成的條碼圖片,需要通過讀取圖片中的條碼信息,如條碼類型、條碼繪製區域在圖片中的四個頂點坐標位置等,可參考本文中的方法。 註:讀取時,也支持讀取二維碼類型。 引入dll 調用API:Spire.B ...
  • 大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT10xx系列MCU外接24MHz晶振的作用。 痞子衡之前寫過一篇關於時鐘引腳的文章 《i.MXRT1xxx系列MCU時鐘相關功能引腳的作用》,裡面簡單提及了外部晶振相關引腳的作用,但是並沒有詳細展開。最近在客戶支持中,有客戶 ...
  • MySQL基礎知識02 4.CRUD 資料庫CRUD語句:增(create)、刪(delete)、改(update)、查(Retrieve) Insert 語句 (添加數據) Update 語句(更新數據) Delete 語句(刪除數據) Select 語句 (查找數據) 指對資料庫中表記錄的操作( ...
  • MySQL基本知識 1.資料庫 1.1.創建資料庫 語法: CREATE DATABASE [IF NOT EXISTS] db_name [create_specification[,create_specification]...] create_specification: [DEFAULT] ...
  • 一、在Bootstra5中使用媒體對象 Bootstrap 媒體對象在版本 5 中已經停止支持了。但是,我們仍然可以使用 flex 和 margin 創建包含左對齊或右對齊媒體對象(如圖像或視頻)以及文本內容(如博客評論、推文等)的佈局 。 <!doctype html> <html lang="z ...
  • 一、節流 概念:在規定的間隔時間範圍內不會重覆觸發回調,只有大於這個時間間隔才會觸發回調,把頻繁觸發變為少量觸發。 類似於技能CD。 應用:點擊按鈕,輪播圖點擊左右箭頭。 插件lodash.js,它裡面封裝了函數的防抖與節流業務。 <p>計數器:<span>0</span></p> <button> ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...