1. 程式人生 > 其它 >leetcode231. 2 的冪(位運算)

leetcode231. 2 的冪(位運算)

Spring概述

Spring:一個java框架,使用java語言開發的,輕量級的,開源的框架,可以在j2se,j2ee專案中使用,

Spring核心技術:IoC(Inversion of Control,控制反轉),AOP(Aspect Oriented Programming)

Spring又叫做容器,spring作為容器,可以讓spring建立java物件,給屬性賦值。

Spring作用:實現解耦合,解決java物件之間的耦合,解決模組之間的耦合。

Spring作為容器適合管理的物件:service物件,dao物件,工具類物件

Spring作為容器不適合管理的物件:實體類,servlet,listener,filter等web中的物件,她們是tomcat建立和管理的。

Spring的地址

官網地址:https://spring.io/

Spring的優點:

Spring 是一個框架,是一個半成品的軟體。有 20 個模組組成。它是一個容器管理物件, 容器是裝東西的,Spring 容器不裝文字,數字。裝的是物件。Spring 是儲存物件的容器。

(1) 輕量,

Spring 框架使用的 jar 都比較小,一般在 1M 以下或者幾百 kb。Spring 核心功能的所需 的 jar 總共在 3M 左右。 Spring 框架執行佔用的資源少,執行效率高。不依賴其他 jar

(2) 針對介面程式設計,解耦合

Spring 提供了 Ioc 控制反轉,由容器管理物件,物件的依賴關係。原來在程式程式碼中的 物件建立方式,現在由容器完成。物件之間的依賴解耦合。 Spring 是於 2003 年興起的一個輕量級的 Java 開發框架,它是為了解決企業應用開發 的複雜性而建立的。Spring 的核心是控制反轉(IoC)和麵向切面程式設計(AOP)。Spring 是可 以在 Java SE/EE 中使用的輕量級開源框架。

(3) AOP 程式設計的支援

通過 Spring 提供的 AOP 功能,方便進行面向切面的程式設計,許多不容易用傳統 OOP 實現 的功能可以通過 AOP 輕鬆應付 在 Spring 中,開發人員可以從繁雜的事務管理程式碼中解脫出來,通過宣告式方式靈活地 進行事務的管理,提高開發效率和質量。

(4) 方便整合各種優秀框架

Spring 不排斥各種優秀的開源框架,相反 Spring 可以降低各種框架的使用難度,Spring 提供了對各種優秀框架(如 Struts,Hibernate、MyBatis)等的直接支援。簡化框架的使用。 Spring 像插線板一樣,其他框架是插頭,可以容易的組合到一起。需要使用哪個框架,就把 這個插頭放入插線板。不需要可以輕易的移除。

IoC控制反轉

2.1概念

控制反轉(IoC,Inversion of Control),是一個概念,是一種思想。指將傳統上由程式代 碼直接操控的物件呼叫權交給容器,通過容器來實現物件的裝配和管理。控制反轉就是對對 象控制權的轉移,從程式程式碼本身反轉到了外部容器。通過容器實現物件的建立,屬性賦值, 依賴的管理。

IoC 是一個概念,是一種思想,其實現方式多種多樣。當前比較流行的實現方式是依賴 注入。應用廣泛。

IoC把建立物件的過程交給Spring進行管理

1.IoC分為控制和反轉:

控制:物件建立,屬性賦值,物件生命週期管理

反轉:把開發人員管理物件的許可權轉移給了程式碼之外的容器實現,由容器完成物件的管理。

正轉:開發人員在程式碼中,使用new構造方法建立物件,開發人員掌握了物件的建立,屬性賦值,物件從開始到銷燬的全過程,開發人員有對物件全部控制。

通過容器,可以使用容器中的物件(容器已經建立了物件,物件屬性賦值了,物件也組裝好了)。

2.IoC的技術實現:

DI(依賴注入):Dependency Injection,是IoC的一種技術實現,程式只需要提供要使用的物件的名稱就可以了,物件如何建立,如何從容器中查詢,獲取都由容器內部自己實現。

3.Spring框架使用的DI實現IoC

通過spring框架,只需要提供要使用的物件名詞就可以了,從容器中獲取名稱對應的物件,Spring底層使用的是反射機制,通過反射建立物件,屬性

2.1.2

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

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

1)BeanFactory:IOC容器基本實現,是Spring內部的使用介面,不提供開發人員進行使用,其在載入配置檔案時候不會建立物件,在獲取物件(使用)才去建立物件

2)ApplicationContext:BeanFactory介面的子介面,提供更多更強大的功能,一般由開發人員使用,並且在載入配置檔案的時候就會建立物件。

2.2Spring的配置檔案

<?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="someService" class="com.hao.service.impl.SomeServiceImpl"/>
<!--bean裡面放java物件,class是全限定類名,id是物件標識,是唯一值。-->
</beans>
spring標準配置檔案:
1)根標籤 beans
2)beans後面是約束檔案說明
3)beans裡面是bean宣告
4)bean:bean就是java物件,spring容器管理的java物件,叫做bean

2.3spring容器建立物件的特點

1.容器物件ApplicationContext:介面

通過ApplicationContext物件,獲取要使用的其他Java物件,執行getBean(“<bean>的id”)

2.Spring預設的是呼叫類的無引數構造方法,建立物件。

3.spring讀取配置檔案,一次建立好所有的java物件,都放到map中。

2.4獲取容器中定義的物件資訊

//獲取配置檔案中定義的物件個數
int num=cxt.getBeanDefinitionCount();
//獲取配置檔案中所有物件的名稱
String names[]=cxt.getBeanDefinitionNames();

2.5DI:給屬性賦值

spring呼叫類的無參構造方法,建立物件,物件建立後給屬性賦值

給屬性賦值可以使用

1)xml配置檔案中的標籤和屬性;

2)使用註解

DI分類:1.set注入,也叫作設值注入;2.構造注入

2.5.1基於xml的DI

在xml配置檔案中使用標籤和屬性,完成物件建立,屬性賦值

1)set注入,也叫作設值注入

概念:spring呼叫類中的set方法,在set方法中可以完成屬性賦值,推薦使用。

  <!--
DI:給屬性賦值
簡單型別:java中的基本資料型別和String
1.set注入:spring呼叫類的set方法,通過set方法完成屬性賦值
簡單型別的set注入
語法:<bean id="xxx" class="yyyy">
<property name="屬性名" value="簡單型別屬性值"/>
....
</bean>
-->
<bean id="myStudent" class="com.hao.jh01.Student">
<!--賦值的時候會自動呼叫類中的set方法,比如name=“age”,呼叫setAge方法-->
<property name="age" value="10"/><!--執行了setAge=10-->
<property name="name" value="張三"/><!--執行了setName="張三"-->
</bean>
    <!--
2.set注入:
引用類型別的set注入:
語法:<bean id="xxx" class="yyyy">
<property name="屬性名" ref="bean的id"/>
....
</bean>
-->
<bean id="myStudent" class="com.hao.jh02.Student">
<property name="age" value="10"/><!--執行了setAge=10-->
<property name="name" value="張三"/><!--執行了setName="張三"-->
<property name="school" ref="mySchool"/>
</bean>
<bean id="mySchool" class="com.hao.jh02.School">
<property name="name" value="新鄉學院"/>
<property name="address" value="紅旗區"/>
</bean>

給屬性注入空值的方法:

  <bean id="myStudent" class="com.hao.jh02.Student">
<property name="age" value="10"/><!--執行了setAge=10-->
<property name="name"><!--表示給name注入null值,輸出為null-->
<null/>
</property>
</bean>

屬性值包含特殊符號的時候

1)使用xml實體符號進行轉義

&lt;相當於<

&gt;相當於>

2)把帶有特殊符號的內容寫到CDATA

<property name="name"><!--表示給name注入<<南京>>,輸出<<南京>>-->
<value><![CDATA[<<南京>>]]></value>
</property>

2)構造注入

構造注入:spring呼叫類中的有參構造方法,在建立物件的同時,給屬性賦值。

使用name屬性賦值:

  <!--
構造注入:Spring呼叫類的有引數構造方法,建立物件同時給屬性賦值
語法:
<bean id="xxx" class="yyy">
<constructor-arg>:表示一個構造方法的形參
標籤有屬性: name:構造方法的形參名
index:構造方法的引數位置
value:簡單型別的形參值
ref:引用型別的形參值
<bean>
-->
<bean id="myStudent" class="com.hao.jh03.Student">
<constructor-arg name="age" value="11"/>
<constructor-arg name="name" value="張三"/>
<constructor-arg name="school" ref="mySchool"/>
</bean>
<bean id="mySchool" class="com.hao.jh03.School">
<property name="name" value="新鄉學院"/>
<property name="address" value="紅旗區"/>
</bean>

使用index屬性賦值

  <!--構造注入,使用index,引數的位置,構造方法引數從左到右的位置依次是0,1,2-->
<bean id="myStudent02" class="com.hao.jh03.Student">
<constructor-arg index="0" value="12"/>
<constructor-arg index="1" value="李四"/>
<constructor-arg index="2" ref="mySchool"/>
</bean>
<!--省略index,如果省略的話,屬性順序一定要與類屬性順序一致-->
<bean id="myStudent03" class="com.hao.jh03.Student">
<constructor-arg value="12"/>
<constructor-arg value="李四"/>
<constructor-arg ref="mySchool"/>
</bean>
<bean id="mySchool" class="com.hao.jh03.School">
<property name="name" value="新鄉學院"/>
<property name="address" value="紅旗區"/>
</bean>

3)引用型別的自動注入

概念:spring可以根據某些規則給引用型別完成賦值,只對引用型別有效

規則有兩個分別為byName和byType

①:byName(按名稱注入):java類中引用型別屬性名稱和spring容器中bean的id名稱一樣的,且資料型別也是一樣的,這些bean能夠賦值給引用型別。

相關程式碼:

<!--
引用型別自動注入:spring根據byName,byType規則給引用型別賦值
1.byName(按名稱注入):java類中引用型別的屬性名稱和spring容器中的bean的id名稱一樣,且資料型別一樣,這樣的bean能夠賦值給引用型別
語法:
<bean id="xxx" class="yy" autowire="byName">
簡單屬性賦值
</bean>
-->

<bean id="myStudent" class="com.hao.jh04.Student" autowire="byName">
<property name="age" value="10"/>
<property name="name" value="張三"/>
<!--
<property name="school" ref="mySchool"/>
-->
</bean>
<bean id="school" class="com.hao.jh04.School">
<property name="name" value="新鄉"/>
<property name="address" value="紅旗區"/>
</bean>

②:byType(按型別注入):java類中引用型別的資料型別和spring容器中的bean的class值是同源關係的,這樣的bean賦值給引用型別。

    <!--

2.byType(按型別注入):java類中引用型別的資料型別和bean的class是同源的,這些的bean能夠賦值給引用型別。

同源關係:
1.java中引用型別的資料型別和bean的class值是一樣的。
2.java中引用型別的資料型別和bean的class值是父子類關係的。
3.java中引用型別的資料型別和bean的class值是介面和實現類關係的。
語法:
<bean id="xxx" class="yy" autowire="byType">
簡單屬性賦值
</bean>
注意:在xml配置檔案中,符合條件的物件只能有一個,多餘一個會報錯。
-->

<bean id="myStudent" class="com.hao.jh05.Student" autowire="byType">
<property name="age" value="10"/>
<property name="name" value="張三"/>
<!--
<property name="school" ref="mySchool"/>
-->
</bean>
<bean id="mySchool" class="com.hao.jh05.School">
<property name="name" value="新鄉"/>
<property name="address" value="紅旗區"/>
</bean>

4)在專案中使用多個spring配置檔案

分多個配置檔案的方式:1)按照功能模組分,一個模組一個配置檔案,2)按類的功能分,資料庫操作相關的類在一個檔案,service類在一個配置檔案,配置redis,事務等等的一個配置檔案。

spring管理多個配置檔案,常用的是包含關係的配置檔案,專案中有一個總的檔案,裡面有一個import標籤包含其他的多個配置檔案

語法:

總的檔案(xml)
<import resource="其他的檔案的路徑1"/>
<import resource="其他的檔案的路徑2"/>
關鍵字“classpath:" :表示類路徑,也就是類檔案(class)所在的目錄。spring到類路徑中載入檔案
什麼時候使用classpath:在一個檔案中要使用其他的檔案,需要使用classpath。
包含關係的配置檔案,可以使用萬用字元(*:表示任意字元)注意:總的檔名稱,不能包含在萬用字元範圍內。

5)注入集合型別的屬性(注入簡單型別)

package com.hao.collectType;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Student {
private String[] course;
private List<String> list;
private Map<String,String> map;
private Set<String> set;

public void setSet(Set<String> set) {
this.set = set;
}

public void setCourse(String[] course) {
this.course = course;
}

public void setList(List<String> list) {
this.list = list;
}

public void setMap(Map<String, String> map) {
this.map = map;
}
public void test(){
System.out.println(Arrays.toString(course));
System.out.println(list);
System.out.println(map);
System.out.println(set);
}
}

配置檔案:

<?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="student" class="com.hao.collectType.Student">
<property name="course">
<array>
<value>java課程</value>
<value>MySql課程</value>
</array>
</property>
<property name="list">
<list>
<value>張三</value>
<value>李四</value>
</list>
</property>
<property name="map">
<map>
<entry key="1" value="中國"></entry>
<entry key="2" value="美國"></entry>
</map>
</property>
<property name="set">
<set>
<value>MySql</value>
<value>PHP</value>
</set>
</property>
</bean>
</beans>

6)注入集合型別的屬性(注入物件型別)

實體類:

package com.hao.collectType;

public class Course {
private String cname;
public void setCname(String cname){
this.cname=cname;
}

@Override
public String toString() {
return "Course{" +
"cname='" + cname + '\'' +
'}';
}
}
package com.hao.collectType;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Student {

private List<Course> courseList;

public void setCourseList(List<Course> courseList){
this.courseList=courseList;
}

public void test(){
System.out.println(courseList);
}
}

配置檔案

<?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="student" class="com.hao.collectType.Student">
<property name="courseList">
<list>
<ref bean="course01"></ref>
<ref bean="course02"></ref>
</list>
</property>
</bean>
<bean id="course01" class="com.hao.collectType.Course">
<property name="cname" value="語文"/>
</bean>
<bean id="course02" class="com.hao.collectType.Course">
<property name="cname" value="數學" />
</bean>

</beans>

測試:

public class MyTest {
@Test
public void test001(){
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
Student student=applicationContext.getBean("student", Student.class);
student.test();
}
}

2.5.2基於註解的DI

基於註解的DI:使用spring提供的註解,完成java物件建立,屬性賦值。

註解使用的核心步驟:

1.在原始碼中加入註解,例如@Component

2.在spring的配置檔案,加入元件掃描器的標籤。

@Component

@Component:表示建立物件,物件放到容器中,作用是<bean>

屬性:value,表示物件名稱,也就是bean的id屬性值

位置:在類的上面,表示建立此類的物件

@Component(value=“myStudent”)(value可以省略)等同於

<bean id="myStudent" class="com.hao.jh01.Student"/>

其中如果只寫@Component的話,會被框架自動賦一個值,這個值為類名首字母小寫。

配置檔案:

<?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 https://www.springframework.org/schema/context/spring-context.xsd">

<!--宣告元件掃描器,使用註解必須加入這個語句
component-scan:翻譯過來是元件掃描器,元件是java物件
屬性:base-package 註解在你的專案中的包名,
框架會掃描這個包和子包中的所有類,找類中的所有註解
遇到註解後,按照註解表示的功能,去建立物件,給屬性賦值。
-->
<context:component-scan base-package="com.hao.jh01"></context:component-scan>
</beans>

和@Component功能相同的建立物件的註解

1)@Repository:放在dao介面的實現類上面,表示建立dao物件,持久層物件,能訪問資料庫

2)@Service:放在業務層介面的實現類上面,表示建立業務層物件,業務層物件有業務的功能

3)@Controller:放在控制器類的上面,表示建立控制器物件。屬於表示層物件,控制器物件能接受請求,把請求的處理結果顯示給使用者。

這四個註解都能建立物件,但是@Repository,@Service,@Controller有角色說明,表示物件是分層的,物件是屬於不同層的,具有額外功能。

掃描多個包的三種方式:

<!--第一種:使用多次元件掃描器-->
<context:component-scan base-package="com.hao.jh01"/>
<context:component-scan base-package="com.hao.jh02"/>
<!--第二種:使用分隔符(;或者,)指定多個包-->
<context:component-scan base-package="com.hao.jh01;com.hao.jh02"/>
<!--第三種:指定父包-->
<context:component-scan base-package="com.hao"/>

@Value

package com.hao.jh02;

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

@Component("myStudent")
public class Student {
/**
* 簡單型別屬性賦值:@Value
* @Value:簡單屬性賦值屬性
* 屬性:value簡單型別屬性值
* 位置:1)在屬性定義的上面,無需set方法,推薦使用
* 2)在set方法的上面
*/
@Value(value="zhangsan")
private String name;
@Value(value = "11")
private int age;

public Student() {
System.out.println("Student類的無參構造被呼叫了");
}

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

@AutoWired 引用型別(注入物件屬性):使用註解方式進行屬性注入

引用型別:@AutoWired:spring框架提供的,給引用型別賦值的,使用自動注入原理,支援byName,byType。預設是byType。

它可以對類成員變數、方法及建構函式進行標註,完成自動裝配的工作

@Autowired屬性:required:boolean型別的屬性,預設為true

true:spring在啟動的時候,建立容器物件的時候,會檢查引用型別是否賦值成功,如果賦值失敗,終止程式執行,並報錯

false:如果引用型別賦值失敗,程式正常執行,不報錯,引用型別的值為null

@Autowired使用位置:1)在屬性定義的上面,無需set方法,推薦使用

2)在set方法的上面。

示例:

//UserDao
package com.hao.dao;

public interface UserDao {
public void add();
}
//UserDao實現類
package com.hao.dao.impl;

import com.hao.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository(value = "userDao")
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("UserDaoImpl add..........");
}
}
//UserService
package com.hao.service;

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

@Service(value="userService")
public class UserService {
@Autowired//根據型別進行注入,找到UserDao類進行注入
private UserDao userDao;
public void add(){
System.out.println("UserDao add......");
userDao.add();
}
}
<!--配置檔案-->
<?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
https://www.springframework.org/schema/context/spring-context.xsd">


<context:component-scan base-package="com.hao"></context:component-scan>
</beans>
//測試檔案
@Test
public void test002(){
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
UserService userService=applicationContext.getBean("userService", UserService.class);
userService.add();
}

@Qualifier:根據名稱進行注入

@Qualifier註解的使用,和@Autowired一起使用

當一個介面有多個實現類的時候,只使用@Autowired註解可能編譯器不知道注入哪個實現類,因此會導致編譯失敗,在@Autowired下面使用@Qualifier的話這可以避免此問題

<!--配置檔案-->
<?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
https://www.springframework.org/schema/context/spring-context.xsd">


<context:component-scan base-package="com.hao"></context:component-scan>
</beans>
//Dao介面
package com.hao.dao;

public interface UserDao {
public void add();
}
//Dao介面實現類UserDaoImple01
package com.hao.dao.impl;

import com.hao.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository(value = "userDaoImpl01")
public class UserDaoImpl01 implements UserDao {
@Override
public void add() {
System.out.println("UserDaoImpl01 add..........");
}
}
//Dao介面實現類UserDaoImpl02
package com.hao.dao.impl;

import com.hao.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository(value="userDaoImpl02")
public class UserDaoImpl02 implements UserDao {
@Override
public void add() {
System.out.println("UserDaoImpl02 add............");
}
}
//UserService
package com.hao.service;

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

@Service(value="userService")
public class UserService {
@Autowired
@Qualifier(value="userDaoImpl02")
private UserDao userDao;
public void add(){
System.out.println("UserDao add......");
userDao.add();
}
}
//測試檔案
@Test
public void test002(){
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
UserService userService=applicationContext.getBean("userService", UserService.class);
userService.add();
}

@Resource 引用型別(注入物件型別屬性)

@Resource:來自jdk中,給引用型別賦值的,支援byName,byType,預設是byName,spring支援這個註解的使用。

使用位置:1)在屬性定義的上面,無需set方法,推薦使用

2)在set方法的上面。

@Rrsource先使用byName賦值,如果賦值失敗,再使用byType。

package com.hao.service;

import com.hao.dao.UserDao;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service(value="userService")
public class UserService {
//根據名稱進行注入 @Resource(name="userDao")
@Resource //根據型別進行注入
private UserDao userDao;
public void add(){
System.out.println("UserDao add......");
userDao.add();
}
}

2.6工廠bean

1.Spring有兩種型別bean,一種普通bean,另外一種工廠bean(FactoryBean)

2.普通bean:在配置檔案中定義的bean型別是什麼類則返回什麼型別

applicationContext.getBean("id")//返回自己定義的類

3.工廠bean:在配置檔案定義bean型別可以和返回型別不一樣。

2.7bean的作用域

1.在Spring裡面,設定建立bean例項是單例項還是多例項。

2.在Spring裡面,預設情況下,bean是單例項物件。

3.如何設定單例項還是多例項

1)在spring配置檔案bean標籤裡面有屬性(scope)用於設定單例項或者多例項。

2)scope屬性值

第一個值 預設值,singleton,表示的是單例項物件

第二個值 prototype,表示的是多例項物件。

3)singleton與prototype的區別

第一:singleton是單例項,prototype是多例項

第二:設定scope值是singleton的時候,載入Spring配置檔案時候就會建立單例項物件。

設定scope值是prototype的時候,不是在載入Spring配置檔案時候建立物件,在呼叫getBean方法時候建立多例項物件。

bean的生命週期

生命週期:從物件建立到物件銷燬的過程。

bean生命週期:

1)通過構造器床架bean例項(無引數構造)

2)為bean的屬性設定值和對其他bean引用(呼叫set方法)

3)呼叫bean的初始化方法(需要進行配置)

4)bean此時可以使用了(獲取到了物件)

5)當容器關閉的時候,呼叫bean的銷燬的方法(需要進行配置銷燬的方法)

AOP面向切面程式設計

3.1 增加功能,導致的問題

在原始碼中,業務方法中增加的功能

1)原始碼可能改動的比較多

2)重複程式碼比較多

3)程式碼難以維護

3.2AOP概念

AOP(Aspect Orient Programming):面向切面程式設計,不修改原始碼進行功能增強。

Aspect:表示切面,給業務方法增加的功能,叫做切面,切面一般都是非業務功能,而且切面功能一般都是可以複用的。例如:日誌功能,事務功能,許可權檢查,引數檢查,統計資訊等等。

怎麼理解面向切面程式設計:以切面為核心設計開發你的應用

1)設計專案時,找出切面的功能,

2)安排切面的執行時間,執行的位置

AOP底層原理

1.AOP底層使用動態代理,其中有兩種情況的動態代理

第一種:有介面的情況下,使用JDK動態代理

建立介面實現類代理物件,增強類的方法

第二種:沒有介面情況,使用CGLIB動態代理。

建立子類的代理物件,增強類的方法。

3.3AOP的作用

1)讓切面功能複用

2)讓開發人員專注業務邏輯,提高開發效率。

3)實現業務功能和其他非業務功能解耦合。

4)給存在的業務方法,增加功能,不用修改原來的程式碼。

3.3AOP中的術語

1)Aspect:切面,給業務方法增加的功能,把通知(Advice)應用到切入點的過程

2)JoinPoint:連線點,連線切面的業務方法,在這個業務方法執行時,會同時執行切面的功能。類中哪些方法可以被增強,這些被增強的方法就是連線點。

3)Pointcut:切入點,是一個或者多個連線點集合。表示這些方法執行時,都能增加切面的功能。表示切面執行的位置。實際被真正增強的方法,就被稱為切入點。

4)target:目標物件,給哪個物件增加切面的功能,哪個物件就是目標物件。

5)Advice:通知(增強),表示切面的執行時間,表示的是在目標方法之前執行切面,還是在目標方法之後執行切面。實際被增強的邏輯部分,稱為通知

AOP中重要的三個要素:Aspect,Pointcut,Advice,這個概念的理解是:在Advice的時間,在Pointcut的位置,執行Aspect。

AOP是一個動態的思想,在程式執行期間,建立代理(ServiceProxy),使用代理執行方法時,增加切面的功能,這個代理物件存在於記憶體中。

3.4 什麼時候使用AOP

要給某些方法增加一些相同的功能,並且原始碼不能修改或者難以修改的時候。給業務方法增加非業務功能時也可以使用AOP。

3.5 AOP技術思想的實現

使用框架AOP,實現AOP的框架有很多,有名的有兩個

1)Spring:Spring框架實現AOP思想中的部分功能,Spring框架實現AOP的操作比較繁瑣,

2)Aspectj:獨立的框架,專門是AOP,屬於Eclipse。Spring框架一般都是基於AspectJ實現AOP操作。

3.6使用AspectJ框架實現AOP

AspectJ:AspectJ不是Spring的組成部分,它是一個基於Java語言的AOP框架。一般把AspectJ和Spring框架一起使用,進行AOP操作。

AspectJ框架可以使用註解(實際開發中推薦使用)和xml配置檔案兩種方式實現AOP

3.6.1基於註解方式實現AOP

AspectJ表示切面執行時間,用的通知(Advice),這個通知可以使用註解表示,

一共有五個註解,表示切面的五個執行時間,這些註解叫做通知註解:

@Before:前置註解

@AfterReturning:後置註解(如果程式有異常,不會執行)

@Around:環繞通知

@AfterThrowing:異常通知

@After:最終通知 (有沒有異常都會執行)

如果要使用這些註解,要在pom.xml中加入依賴

	<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.12</version>
</dependency>

相關程式碼:

<!--配置檔案-->
<?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.hao.user"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
//被增強的類
package com.hao.user;

import org.springframework.stereotype.Component;

@Component(value="user")
public class User {
public void add(){
System.out.println("User add.........");
}
}
//增強User類的類
package com.hao.user;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component(value="userProxy")
@Aspect
public class UserProxy {
@Before(value="execution(* com.hao.user.User.add(..))")
public void before(){
System.out.println("User的增強功能,在User類的Add方法之前執行");
}

@Around(value="execution(* com.hao.user.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
System.out.println("User類的功能增強,在User類的add方法執行前後都會執行");
proceedingJoinPoint.proceed();//執行被增強的方法
System.out.println("之後執行");
}
}
//測試類
@Test
public void test001(){
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
User user=applicationContext.getBean("user", User.class);
user.add();
}
相同切入點的抽取
    @Pointcut(value="execution(* com.hao.user.User.add(..))")
public void pointcut(){}

@Around(value="pointcut()")
public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
System.out.println("User類的功能增強,在User類的add方法執行前後都會執行");
proceedingJoinPoint.proceed();//執行被增強的方法
System.out.println("之後執行");
}
當有多個增強類對同一個方法進行增強時,可以設定增強類優先順序

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

3.6.2 Pointcut 切面執行的位置

切入點表示式作用:可以知道對哪個類裡面的那個方法進行增強。

Pointcut:表示切面執行的位置,使用AspectJ中切入點表示式

切入點表示式語法:execution(訪問許可權 方法返回值 方法宣告(引數) 異常型別)

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

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

execution(* com.hao.dao.UserDao.add(..))

*表示許可權型別:public private等等.....

其中返回型別可以省略不寫

com.hao.dao.UserDao.add(..)表示方法宣告,其中..表示引數列表

舉例二:對com.hao.dao.UserDao類裡面的所有方法進行增強

execution(* com.hao.dao.UserDao.*(..))

第一個*表示許可權型別,第二個*表示UserDao類中的所有方法

舉例三:對com.hao.dao包裡面的所有類所有的的方法進行增強

execution(* com.hao.dao.*.*(..))

3.6.3 @AfterReturning:後置通知

屬性:value 切入點表示式

returning 自定義的變數,表示目標方法的返回值的

自定義變數名稱必須和通知方法的形參名一樣。

位置:在方法的上面

特點:

1.在目標方法之後執行的

2.能獲取到目標方法的執行結果

3.不會影響目標方法的執行。

JdbcTemplate

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

準備工作:

1,引入相關的依賴

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.10</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>

2.在Spring配置檔案配置資料庫連線池

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>

3.配置JdbcTemplate,注入DataSource

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>

4.建立service類,建立dao類,在dao注入jdbcTemplate物件。

Spring整合MyBatis

將 MyBatis 與 Spring 進行整合,主要解決的問題就是將 SqlSessionFactory 物件交由 Spring 來管理。所以,該整合,只需要將 SqlSessionFactory 的物件生成器 SqlSessionFactoryBean 注 冊在 Spring 容器中,再將其注入給 Dao 的實現類即可完成整合。 實現 Spring 與 MyBatis 的整合常用的方式:掃描的 Mapper 動態代理

實現步驟:

1.使用的mysql庫,使用學生表

student2(id int 主鍵列,自動增長,

name varchar(80),

age int);

 create table student2(
-> id int(11) primary key not null auto_increment,
-> name varchar(20) default null,
-> age int(5) default null
-> )engine=innodb,character set=utf8;

2.建立maven專案

3.加入依賴gav

spring依賴,mybatis依賴,mysql依賴

mybatis-spring依賴(mybatis網站上提供的,用來在spring專案中,建立mybatis物件)

spring有關的依賴

注意:mybatis和spring整合的時候,事務是預設自動提交的。

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

<!--Spring依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--Spring事務依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--Spring事務依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--mybatis依賴-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--Spring和Mybatis整合依賴-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--MySQL驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<!--阿里的連線池,德魯伊-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>

加入的相關外掛,防止idea不編譯.xml檔案

	<resources>
<resource>
<directory>src/main/java</directory><!--所在的目錄-->
<includes><!--包括目錄下的.properties,.xml 檔案都會掃描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>

4.建立實體類Student

package com.hao.entity;

public class Student {
private Integer id;
private String name;
private Integer age;

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

public Integer getId() {
return id;
}

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

public String getName() {
return name;
}

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

public Integer getAge() {
return age;
}

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

5.建立dao介面和mapper檔案寫sql語句

package com.hao.dao;

import com.hao.entity.Student;
import org.springframework.stereotype.Repository;

import java.util.List;

public interface StudentDao {
int insertStudent(Student student);
List<Student> selectStudents();
}

StudentDao介面實現類:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hao.dao.StudentDao">
<insert id="insertStudent">
insert into student2(name,age) values(#{name},#{age})
</insert>

<select id="selectStudents" resultType="com.hao.entity.Student">
select * form student2
</select>

</mapper>

6.寫mybatis主配置檔案

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
-->

<typeAliases>
<package name="com.hao.entity"/>
</typeAliases>

<mappers>
<mapper resource="com/hao/dao/StudentDao.xml"/>
</mappers>
</configuration>

7.建立service介面和他的實現類

package com.hao.service;

import com.hao.entity.Student;

import java.util.List;

public interface StudentService {
public int addStudent(Student student);
public List<Student> queryStudent();
}

實現類:

package com.hao.service.impl;

import com.hao.dao.StudentDao;
import com.hao.entity.Student;
import com.hao.service.StudentService;

import java.util.List;

public class StudentServiceImpl implements StudentService {
private StudentDao studentDao;

public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}

@Override
public int addStudent(Student student) {
int rows=studentDao.insertStudent(student);
return rows;
}

@Override
public List<Student> queryStudent() {
List<Student> students=studentDao.selectStudents();
return students;
}
}

8.建立Spring配置檔案

1)宣告資料來源DataSource,使用的阿里的Druid連線池

2)宣告SqlSessionFactoryBean類,在這個類內部建立的是SqlSessionFactory物件。

3)宣告MapperScannerConfiguration類,在內部建立dao代理物件,建立的物件都放在spring容器中。

4)宣告Service物件,把3)中的到賦值給service屬性

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

<!--宣告資料來源DataSource-->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/springdb"></property>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--宣告SqlSessionFactoryBean,在這個類的內部建立SqlSessionFactory-->
<!--其中factory就是建立的SqlSessionFactory物件的名字-->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--指定資料來源-->
<property name="dataSource" ref="myDataSource"/>
<!--指定mybatis的主配置檔案
Resources可以直接使用value屬性賦值
-->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>

<!--宣告MapperScanConfigurer
MapperScannerConfigurer作用:迴圈basePackage所表示的包,把包中每個介面都找到,呼叫sqlSession.getMapper
把每個dao介面都創建出dao物件,dao代理物件放在容器中。
-->
<!--建立dao的代理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定SqlSessionFactory物件的名稱-->
<property name="sqlSessionFactoryBeanName" value="factory"/>
<!--指定基本包,dao介面所在的包名-->
<property name="basePackage" value="com.hao.dao"/>
</bean>
<bean id="studentService" class="com.hao.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"/>
</bean>
</beans>

9.測試dao訪問資料庫

package com.hao;

import com.hao.dao.StudentDao;
import com.hao.entity.Student;
import com.hao.service.StudentService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
@Test
public void test001(){
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
StudentDao studentDao=applicationContext.getBean("studentDao", StudentDao.class);
Student student=new Student();
student.setName("張三");
student.setAge(18);
studentDao.insertStudent(student);
}
@Test
public void test002(){
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
StudentService studentService=applicationContext.getBean("studentService", StudentService.class);
Student student=new Student();
student.setName("李四");
student.setAge(18);
studentService.addStudent(student);
}
}

事務

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

典型場景:銀行轉賬。

事務的四個特性(ACID):原子性,一致性,隔離性,永續性。

事務操作:Spring事務管理介紹

1.事務新增到javaee三層結構裡面的Service層(業務邏輯層)

三層結構:表示層,業務邏輯層,資料訪問層。

2.在Spring進行事務管理操作

1)有兩種方式:程式設計式事務管理和宣告式事務管理(常使用的)

3.宣告式事務管理

1)基於註解方式(使用,方便簡單)

2)基於xml配置檔案方式

4.在Spring進行宣告式事務管理,底層使用AOP

5.Spring事務管理API,提供了一個介面代表事務管理器,這個介面針對不同的框架提供不同的實現類

PlatformTransactionManager介面

1)實現類為DataSourceTransactionManager,用於配置mybatis和jdbc資料來源的事務管理器。

2)實現類為HibernateTransactionManager,用於配置Hibernate的事務管理器。

通過註解方式實現宣告式事務管理

1.在spring配置檔案配置事務管理器

  <!--建立事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入資料來源-->
<property name="dataSource" ref="dataSource"/>
</bean>

2.在spring配置檔案,開啟事務註解

<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

3.在service類上面(獲取service類黎明方法上面)新增事務註解

1)@Transactional,這個註解可以新增到類上面,也可以新增到方法上面

2)如果把這個註解新增到類上面,這個類裡面所有的方法都新增事務。

3)如果把這個註解新增方法上面,就是為這個方法新增事務。

宣告式事務管理引數配置

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

propagation:事務傳播行為,預設為REQUIRED

多事務方法直接進行呼叫,這個過程中事務是如何進行管理的。

事務方法:對資料庫表中資料進行變化的操作。

isolation:事務隔離級別,系統預設的隔離級別是:REPEATABLE READ(可重複讀)

1)事務有一種特性為隔離性,多事務操作之間不會產生影響。不考慮隔離性會產生很多問題。

2)產生的問題為:髒讀,不可重複讀,虛(幻)讀

髒讀:一個未提交的事務讀取到另一個未提交事務的資料。

不可重複讀:一個未提交事務讀取到了另一個已提交事務修改的資料。

虛讀:一個未提交事務讀取到了另一個已經提交的事務新增的資料。

3)通過設定事務隔離性,解決讀問題

timeout:超時時間

1)事務需要在一定時間內進行提交,如果不提交進行回滾

2)預設值是-1(即不超時),設定時間以秒為單位進行計算。

readOnly:是否只讀,預設為false

1)讀:查詢操作,寫:新增修改刪除操作

2)readOnly預設值false,表示可以查詢,可以進行新增修改刪除操作

rollbackFor:回滾

設定出現哪些異常進行事務回滾

noRollbackFor:不回滾

設定出現哪些異常不進行事務回滾。

通過XML方式宣告事務管理

1.在Spring配置檔案中進行配置

第一步:配置事務管理器

第二步:配置通知

第三步:配置切入點和切面。

我的第一個Spring專案

1.新建maven專案

2.加入依賴,修改pom.xml

spring-context:spring依賴

junit:單元測試

3.開發人員定義類:介面和實現類

類也可以沒有介面。

介面和實現類定義方法和沒有Spring時的定義方式一樣。

4.建立spring的配置檔案,

作用:宣告物件,把物件交給spring建立和管理。

使用<bean>表示物件宣告,一個bean表示一個java物件。

5.使用容器中的物件

建立一個表示spring容器的物件,ApplicationContext

String config="beans.xml";//spring的配置檔案
ApplicationContext cxt=new ClassPathXmlApplicationContext(config);//建立容器
/*
注意:容器一旦被建立,bean檔案裡面的所有物件就會被立刻創建出來。
此種方式優點:
獲取物件的速度快,因為物件已經被建立好了
缺點:
佔記憶體
在建立容器(ApplicationContext)物件時,會把配置檔案中的所有物件都創建出來(spring預設規則),即使兩個物件的路徑一樣,只是id名不一樣也會被都創建出來。
*/

Spring建立物件,預設是呼叫類的無參構造方法。

從容器中根據名稱獲取物件,使用getBean(“物件名稱”)