目錄
3.5
3.5.1、spring建立第三方bean對象(方式一)
3.5.2 spring引用外部配置檔案(方式二)
3.5.3 spring基于xml檔案的自動裝配
3.6
3.6.1 SpEL(spring表達式語言,可以節省大量Java代碼)
3.7
3.7.1 springioc容器的注解
3.7.2 定義掃描包時,包含的類和不包含的類:
3.7.3 @AutoWired自動注入
3.7.4 @AutoWired可以進行定義在方法上
3.7.5 自動裝配的注解@AutoWired、@Resource
3.7.5 泛型依賴注入
3.5
3.5.1、spring建立第三方bean對象(方式一)
在Spring中,很多對象都是單執行個體的,在日常的開發中,我們經常需要使用某些外部的單執行個體對象,例如資料庫連接配接池,下面講解如何在spring中建立第三方bean執行個體
導包:
xml檔案:ioc
//spring管理第三方bean:
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
<property name="url" value="jdbc:mysql://localhost:3306/demo">
</property>
<property name="driverClassName" value="com.mysql.jdbc.Driver">
</property>
</bean>
java檔案:MyText(測試)
DruidDataSource dataSource = context.getBean("dataSource", DruidDataSource.class);
System.out.println(dataSource);
System.out.println(dataSource.getConnection());
3.5.2 spring引用外部配置檔案(方式二)
db.properties檔案:
jdbc.username=root
jdbc.password=123456
url=jdbc:mysql://localhost:3306/demo
driverClassName=com.mysql.jdbc.Driver
xml檔案:ioc
↓
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
·
·
·
//當需要引入外部的配置檔案的時候,需要導入一些context的命名空間
<context:property-placeholder
location(位置)="classpath:db.properties">
</context:property-placeholder>
在配置檔案編寫屬性的時候需要注意:
spring容器在進行啟動的時候,會讀取目前系統的某些環境變量的配置,
目前系統的使用者名是用username來表示的,是以最好的方式是添加字首來做區分(如jdbc.)
============================== 1.1、 ================================
<bean id="person" class="com.mashibing.bean.Person">
<property name="name" value="${jdbc.username}"></property>
</bean>
============================== 1.2、 ================================
<bean id="dataSource2"class="com.alibaba.druid.pool.DruidDataSource">
<property name="username"value="${username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="url" value="${url}"></property>
<property name="driverClassName"value="${driverClassName}">
</property>
</bean>
============================== 2、 ==================================
<bean id="person" class="com.mashibing.bean.Person">
<property name="name" value="${jdbc.username}"></property>
</bean>
java檔案:MyText(測試)
============================== 1、 ==================================
DruidDataSource dataSource = context.getBean("dataSource2", DruidDataSource.class);
System.out.println(dataSource);
System.out.println(dataSource.getConnection());
============================== 2、 ==================================
Person person = context.getBean("person2", Person.class);
System.out.println(person);
執行後:
(沒改之前,最開始執行了一次,後面預設就root,而不是root123)
解決:2、中加jdbc.
3.5.3 spring基于xml檔案的自動裝配
xml檔案:ioc
//spring中的自動裝配
/*
*<bean id="address1" class="com.mashibing.bean.Address">
* <property name="province" value="河北"></property>
* <property name="city" value="邯鄲"></property>
* <property name="town" value="武安"></property>
*</bean>
*/
<bean id="address2" class="com.mashibing.bean.Address">
<property name="province" value="河北2"></property>
<property name="city" value="邯鄲2"></property>
<property name="town" value="武安2"></property>
</bean>
<bean id="person" class="com.mashibing.bean.Person"autowire="byType">
</bean>
java檔案:MyText(測試)
Person person = context.getBean("person", Person.class);
System.out.println(person);
(某些情況address1也能行)
在spring中,可以使用自動裝配的功能(spring會把某些bean注入到另外bean中)
可以使用autowire屬性來實作自動裝配,有以下幾種情況
=====================================================================
default/no: 不自動裝配
=====================================================================
byName:按照id來進行裝配,根據set方法後面的名稱首字母小寫決定的,不是參數清單的名稱,如果找不到則裝配null
java檔案:Person(個人)
改:在set方法中,将setAddress()名改setAaddress()
(為null找不到,是以隻能改有參函數名不能改方法名)
=====================================================================
byType:按照bean的類型來進行裝配,如果有多個類型,就會報錯,不知道選擇哪一個具體的類型,如果找不到則裝配null
(加載所有的屬性)
=====================================================================
constructor:按照構造器進行裝配,首先按照類型進行判斷,如果有多個類型相同的bean,再按照id去進行判斷,如果找不到則裝配null
按照構造器進行裝配,先按照有參構造器參數的類型進行裝配,沒有就直接裝配null;如果按照類型找到了多個,那麼就使用參數名作為id繼續比對,找到就裝配,找不到就裝配null
java檔案:Person(個人)
添加:
(必須隻添加單個)
也會null:
3.6
3.6.1 SpEL(spring表達式語言,可以節省大量Java代碼)
xml檔案:ioc
<bean id="person2" class="com.mashibing.bean.Person">
=====================================================================
//可以引入bean對象的屬性
<property name="name" value="#{address.province}"></property>
=====================================================================
//可以支援運算符的所有操作
<property name="age" value="#{12*2}"></property>
//可以引入外部bean
<property name="address" value="#{address}"></property>
=====================================================================
//可以調用靜态方法
<property name="gender" value="#{T(java.util.UUID).randomUUID().toString().substring(0,5)}">
</property>
=====================================================================
//調用非靜态方法
<property name="hobbies" value="#{address.getCity()}"></property>
</bean>
java檔案:MyText(測試)
Person person = context.getBean("person2", Person.class);
System.out.println(person);
3.7
3.7.1 springioc容器的注解
xml檔案:pom
直接将上一個包的複制過來即可
4.12
xml檔案:applicationContext(應用上下文、配置檔案)
<bean id="personController" class="com.mashibing.controller.PersonController" ></bean>
java檔案:PersonController(個人控制器)
@Controller //控制器
//@Scope(value = "prototype")
public class PersonController {
}
java檔案:PersonDao(個人包)
@Repository //倉庫
public class PersonDao {
}
java檔案:PersonService(個人服務)
@Service //服務
public class PersonService {
}
方式一:(掃描整個包)
java檔案:MyText(測試)
//測試的方法不可以有參數,不可以有傳回值
@Test
public void test01() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("applicationContext.xml");
PersonController personController = context.getBean("personController", PersonController.class);
System.out.println(personController);
}
在之前的操作中我們都是使用bean标簽的方式向IOC容器中注冊bean,上面使用的是注解方式
========================================================
@Component(元件):可以在任意的類上進行添加,在掃描的時候都會完成bean的注冊
@Controller(控制器):放置在控制層,用來接受使用者的請求
@Service(服務):放置在業務邏輯層
@Repository(倉庫、包):放置在資料通路層
@Component(元件):給不屬于以上基層的元件添加此注解
@Scope(範圍):注解可以聲明目前類是單例還是多例
注意:
1、這四個注解寫在類上面的時候都可以完成注冊bean的功能,但是這些規定并不是spring識别的辨別
2、在spring程式運作過程中,不會對這四個注解做任何區分,看起來是一樣的,都會完成bean的注冊功能
3、spring底層是不會給具體的層次驗證注解,這樣寫的目的隻是為了提高可讀性(最偷懶的方式,就是給所有想交由IOC容器管理的bean對象添加@component)
4、(未掃描到)
在使用注解的時候,還需要告訴spring應該從上面四個包中,從哪個包開始掃描,一般在定義的時候都寫上相同包的路徑
解決方式:
定義自動掃描的基礎包:(是否要注冊bean到IOC容器中)
下面的base-package:指定掃描的基礎包,spring在啟動的時候會将基礎包及子包下所有加了注解的類都自動掃描進IOC容器
xml檔案:applicationContext(應用上下文、配置檔案)
注意:注解注冊元件和配置檔案注冊元件是一樣的,但是要注意:
(1)元件的id,預設就是元件的類名(首字元小寫),如果改名字的話,直接在注解中修改即可
========================================================
(2)元件預設情況下都是單例的,如果需要配置多例模式的話,可以在注解下添加@Scope(範圍)
java檔案:MyText(測試)
//測試的方法不可以有參數,不可以有傳回值
@Test
public void test01() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("applicationContext.xml");
//指派給兩個對象
PersonController personController = context.getBean("personController", PersonController.class);
PersonController personController2 = context.getBean("personController", PersonController.class);
System.out.println(personController == personController2);
}
(true表示單例模式)
方式一:(之前的)
xml檔案:applicationContext(應用上下文、配置檔案)
方式二: (@Scope(範圍)可以聲明目前是單例還是多例)
java檔案:PersonController(個人控制器)
清空xml檔案:applicationContext内的:
========================================================
5、需要手動導入context(上下文)命名空間
(因為建立一個配置檔案時,需要手動添加裡面的命名空間)
方式二:(掃描指定的類)
6、在使用注解的時候沒有定義id和class,那麼如何根據id來進行識别
預設是把目前類的名稱的首字母小寫之後作為id,如果需要改變名稱,那麼需要在注解後面添加參數值value來完成修改名字的目的
java檔案:PersonController(個人控制器)
java檔案:MyText(測試)
改:
3.7.2 定義掃描包時,包含的類和不包含的類:
指定隻掃描哪些元件,預設情況下是全部掃描的,是以此時要配置的話需要在component-scan标簽上添加 use-default-filters="false"
java檔案:PersonController(個人控制器)
//測試的方法不可以有參數,不可以有傳回值
@Test
public void test01() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("applicationContext.xml");
//指派給兩個對象
PersonController personController = context.getBean("personController", PersonController.class);
PersonController personController2 = context.getBean("personController", PersonController.class);
System.out.println(personController == personController2);
}
xml檔案:applicationContext(應用上下文、配置檔案)
<context:component-scan base-package="com.mashibing">
//當定義好注解的掃描路徑之後,可以做更細粒度的控制,可以選擇掃描哪個注解,也可以選擇不掃描哪個注解:
exclude-filter(排除過濾器):表示要排除掃描的注解,使用較多
include-filter(包含過濾器):表示要包含掃描的注解,一般不會用此規則,用另一個排除過濾器就行了但是如果引入的第三方包中包含注解,此時就需要使用此标簽來進行辨別
兩個不能同時存在?
=================== 下面用的 exclude-filter(排除過濾器)======================
type(類型):規則的類型
expression(表達式):表達式
===============================================================================
assignable(可轉讓):可以指定對應的類的名稱。但是表達式必須是完全限定名(完整的的路徑,不可以寫包的路徑)
<context:component-scan base-package="com.mashibing">
//因為上面的寫了base-package="com.mashibing",裡面的可以不用寫
// <context:exclude-filter type="assignable" expression=
// "com.mashibing.controller.PersonController(個人控制器)"/>
</context:component-scan>
(正常)
===============================================================================
annotation(注解):按照注解來進行排序,但是表達式中必須是注解的完全限定名
填入:
===============================================================================
aspectj(實作):使用切面的方式,一般不用
===============================================================================
custom(自定義):使用自定義的方式,可以自己定義自己的篩選規則,一般不用
===============================================================================
regex(正規表達式):使用正規表達式的方式,一般不用
當定義好基礎掃描的包之後,可以排除包中的某些類,使用如下的方式:
assignable(可轉讓):指定排除某個具體的類,按照類排除,expression裡寫不注冊的具體類名路徑
annotation(注解):按照注解進行排除,标注了指定注解的元件不要,expression裡寫要過濾的注解路徑
aspectj(實作):後面講aop的時候說明要使用的aspectj表達式,一般不用
custom(自定義):定義一個typeFilter,自己寫代碼決定哪些類被過濾掉,一般不用
regex(正規表達式):使用正規表達式過濾,一般不用
3.7.3 @AutoWired自動注入
xml檔案:applicationContext(應用上下文、配置檔案)
include-filter(包含過濾器):表示要包含掃描的注解,一般不會用此規則,用另一個排除過濾器就行了但是如果引入的第三方包中包含注解,此時就需要使用此标簽來進行辨別 ==================== 下面用的include-filter(包含過濾器)========================
<context:include-filter type="assignable" expression=
"com.mashibing.service.PersonService"/>
java檔案:PersonController(個人控制器)
@Controller
public class PersonController {
@Autowired
private PersonService personService2;
public void save() {
personService2.save();
}
}
java檔案:PersonService(個人伺服器)
@Service
public class PersonService {
@Autowired
private PersonDao personDao;
public void save(){
//System.out.println("personservice"); //應用
personDao.save();
}
}
java檔案:PersonDao(個人包)
@Repository
public class PersonDao {
public void save(){System.out.println("儲存成功");}
//public void update(){System.out.println("更新成功");}
}
java檔案:MyTest(測試)
public class MyTest {
@Test
public void test01() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("applicationContext.xml");
PersonController personController = context.getBean("personController", PersonController.class);
//System.out.println(personController);
personController.save();
}
========================================================
java檔案:PersonService2(個人伺服器2)
@Service
public class PersonService2 extends PersonService{
@Autowired
private PersonDao personDao;
public void save(){
System.out.println("personservice2...........");
personDao.save();
}
}
1、預設情況下是按照ByType來進行裝配的,如果找到直接指派,找不到報錯
如下面案例:
通過@AutoWired注解能夠完成自動注入的功能,是按照什麼方式進行自動注入的呢?
如果有多個類型一樣的bean對象,此時會按照id來進行查找,預設的id是類名的首字元小寫那個,
如果找到了直接注入,如果找不到那麼就報錯
注意:當使用AutoWired注解時,自動裝配是根據類型方式:
1、如果隻找到一個,則直接進行指派,
2、如果沒有找到,則直接抛出異常(包括去掉@Service結果也會報錯)
3、如果找到多個,那麼會按照變量名作為id繼續比對
(1)比對上直接進行裝配
(2)如果比對不上則直接報異常
還可以使用@Qualifier注解來指定id的名稱,讓spring不要使用變量名,當使用@Qualifier注解的時候也會有兩種情況:
1、找到,則直接裝配
2、找不到,就會報錯
java檔案:PersonController(個人控制器)
如果不加入@Qualifier的話結果就為personservice2...........
========================================================
當@AutoWired添加到方法上的時候,此方法在建立對象的時候會預設調用,同時方法中的參數會進行自動裝配
java檔案:PersonController(個人控制器)
@Autowired
public void test(@Qualifier("personDao") PersonDao personDao123) {
System.out.println("test");
personDao123.update();
}
========================================================
方式一:
java檔案:PersonDao(個人包)
java檔案:PersonController(個人控制器)
3.7.4 @AutoWired可以進行定義在方法上
方式二:@Qualifier注解也可以定義在方法的參數清單中,可以指定目前屬性的id名稱
3.7.5 自動裝配的注解@AutoWired、@Resource
java檔案:PersonController(個人控制器)
1、@Resource是jdk提供的功能,@AutoWired是spring提供的功能,依靠的是Java标準
2、
@Resource可以在其他架構中使用,擴充性好
@AutoWired隻能在spring中使用,支援的架構比較單一
3、
@AutoWired是按照類型(屬性)進行裝配,如果類型(屬性)找不到那麼就使用名字(屬性名)進行查找
@Resource是按照名稱(屬性名)進行裝配,如果名字找不到,那麼就使用類型方式(屬性)
2、@AutoWire:預設是按照類型進行裝配,預設情況下要求依賴的對象必須存在,@Resource預設是按照名字進行比對的,同時可以指定name屬性。
3、@AutoWired:隻适合spring架構,而@Resource擴充性更好
========================================================
其他方式:
<bean id="personController" class="com.mashibing.controller.PersonController" autowire=""></bean>
3.7.5 泛型依賴注入
java檔案:Student(學生)
public class Student { }
java檔案:Teacher(老師)
public class Teacher { }
java檔案:BaseController(基本控制器)
java檔案:BaseDao(基本包)
public abstract class BaseDao<T> {
public abstract void save();
}
java檔案:StudentDao(學生包)
@Repository
public class StudentDao extends BaseDao {
public void save() {
System.out.println("儲存學生");
}
}
java檔案:TeacherDao(老師包)
@Repository
public class TeacherDao extends BaseDao {
public void save() {
System.out.println("儲存老師");
}
}
java檔案:MyTest(測試)
@Test
public void test02() {
BaseController baseController = context.getBean("baseController", BaseController.class);
baseController.save();
baseController.save2();
}
java檔案:PersonController(個人控制器)
關掉:
方式二:(泛型方式)實作具體類
java檔案:BaseController(基本控制器)
改:
java檔案:MyTest(測試)
@Test
public void test02() {
BaseController baseController = context.getBean("baseController", BaseController.class);
baseController.save();
}
java檔案:BaseController(基本控制器)
改:
========================================================
方式一:(普通方式)
java檔案:StudentService(學生服務) java檔案:TeacherService(老師服務)
java檔案:MyTest(測試)
@Test
public void test02() {
StudentService studentService = context.getBean("studentService", StudentService.class);
studentService.save();
TeacherService teacherService = context.getBean("teacherService",
TeacherService.class);
teacherService.save();
}
}
方式二:(泛型方式)
java檔案:BaseService(基本服務)
public class BaseService<T> {
@Autowired
private BaseDao<T> baseDao;
public void save(){
baseDao.save();
}
}
java檔案:StudentService(學生服務)
@Service
public class StudentService extends BaseService<Student>{ }
java檔案:TeacherService(老師服務)
@Service
public class TeacherService extends BaseService<Teacher> { }