Spring 概述
-
Spring是一個開源框架
-
Spring爲簡化企業級開發而生,使用Spring,JavaBean就可以實現很多以前要靠EJB才能實現的功能。同樣的功能,在EJB中要通過繁瑣的配置和複雜的代碼才能夠實現,而在Spring中卻非常優雅和簡潔
-
Spring是一個IOC(DI)和AOP容器框架
-
Spring的優良特性
①,非侵入式:基於Spring開發的應用中的對象可以不依賴於Spring的API
②,依賴注入:DI–Dependency Injection,反轉控制(IOC)最經典的實現
③,面向切面編程:Aspect Oriented Programming – AOP
④,容器:Spring是一個容器,因爲它包含並且管理應用對象的生命週期
⑤,組件化:Spring實現了使用簡單的組件配置組合成一個複雜的應用。在Spring中可以使用xml和Java註解組合這些對象
⑥,一站式:在IOC和AOP的基礎上可以整合各種企業應用的開源框架和優秀的第三方類庫(實際上Spring自身也提供了表述層的SpringMVC和持久層SpringJDBC)
-
Spring模塊
-
使用eclipse需要加入JAR包
-
Spring自身JAR包:Spring-framework-4.0.0.RELEASE\libs目錄下
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar -
commons-logging-1.1.1.jar
-
-
在Spring Tool Suite工具中通過如下步驟創建Spring的配置文件
- ①,File -->New Spring Bean Configuration File
- ②,爲文件取名字,例如:applicationContext.xml
- 創建一個Spring項目
- 創建項目後idea自帶Spring的jar包,所以不需要導入
- 創建Person類
public class Person {
private Integer age;
private String name;
}
- 配置applicationContext.xml文件
<?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>:定義spring所管理的一個對象
<id>:該對象的唯一標示,注意:不能重複
<class>:此對象所屬類的權限定名-->
<bean id="person" class="com.Person">
<!-- <property> :爲對象的某個屬性賦值
name:屬性名
value:屬性值-->
<property name="age" value="1"></property>
<property name="name" value="Tommmey周"></property>
</bean>
</beans>
- 創建PersonTest測試類測試
public class PersonTest {
@Test
public void demo01(){
//初始化容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//通過getBean()獲取對象
//Person person = (Person)ac.getBean("person");
// 使用此方法獲取對象時,要求spring所管理的此類型的對象只能有一個
// Person person = ac.getBean(Person.class);
Person person = ac.getBean("person2",Person.class);
System.out.println(person);
}
}
IOC 容器和 Bean 的配置
-
IOC(Inversion of Control):反轉控制(把原來由程序員管理的對象的權力,反轉給程序本身,讓程序自己管理),也叫控制反轉
-
在應用程序中的組件需要獲取資源時,傳統的方式是組件主動的從容器中獲取所有需要的資源,在這樣的模式下開發人員往往需要知道在具體容器中特點資源的獲取方式,增加了學習成本,同時降低了開發效率
-
反轉控制的思想完全顛覆了應用程序組件獲取資源的傳統方式:反轉了資源的獲取方向-- -改由容器 主動的將資源推送給需要的組件,開發人員不需要知道容器是如何創建資源對象的,只需要提供接收資源的方式即可,極大的降低了學習成本,提高了開發的效率。這種行爲也稱爲查找的被動形式。
-
傳統方式:我想喫飯 我需要買菜做飯
-
反轉控制:我想喫飯 飯來張口
DI(Dependency Injection):依賴注入
- IOC的另一種表述方式:即組件以一些預先定義好的方式(例如: setter 方法)接受來自於容器的資源注入。相對於IOC而言,這種表述更直接。
總結:IOC就是一種反轉控制的思想,而DI是對IOC的一種具體實現。
-
IOC容器在Spring中的實現
前提: Spring 中有IOC思想,IOC 思想必須基於IOC 容器來完成,而IOC容器在最底層實質上就是一個對象工廠
在通過IOC容器讀職Bean的實例之前,需要先將IOC容器本身實例化。
Spring提供了IOC容器的兩種實現方式:
①,
BeanFactory:IOC
容器的基本實現,是Spring內部的基礎設施,是面向Spring本身的,不是提供給開發人員使用的。
②,ApplicationContext:BeanFactory
的子接口,提供了更多高級特性。面向Spring的使用者,幾乎所有場合都使用ApplicationContext而不是底層的BeanFactory. -
ApplicationContext
的主要實現類①,
ClassPathXmlApplicationContext
:對應類路徑下的XML格式的配置文件②,
FileSystemXmlApplicationContext
: 對應文件系統中的XML格式的配置文件③,在初始化時就創建單例的 bean,也可以通過配置的方式指定創建的Bean是多實例的
-
ConfigurableApplicationContext
①,是AplcationContext的子接口,包含一些擴展方法
②,refresh()和 close()讓ApliatinonContext具有啓動、關閉和刷新上下文的能力。
-
1)通過依賴注入的方式
-
通過bean的setXxx()方法賦值
-
通過bean的構造器賦值
-
<bean id="person3" class="com.Person">
<constructor-arg value="3" />
<constructor-arg value="Tommey3" index="1"/><!-- index通過索引指定參數位置 -->
</bean>
-
2) p名稱空間
- 爲了簡化XIML文件的配置,越來越多的XML文件採用屬性而非子元素配置信息,Spring從2.5版本開始引入了一個新的p命名空間,可以通過<bean>元素屬性的方式配置Bean的屬性。使用p命名空間後,基於XML的配置方式將進一步簡化。
-
3)賦值可使用的值
①,字面量
-
可以使用字符串表示的值, 可以通過value屬性或value子節點的方式指定
-
基本數據類型及其封裝類、 String 等類型都可以採取字面值注入的方式
-
若字面值中 包含特殊字符,可以使用<![CDATA[]]>把字 面值包裹起來
②,null值
③,給bean的級聯屬性賦值
④,外部已聲明的bean,引用其他的bean
⑤,內部bean
- 當bean實例僅僅給一個特定的屬性使用時,可以將其聲明爲內部bean。內部bean聲明直接包合在<property>或<constructor-arg>元素裏,不需要設置任何id或name屬性
- 內部bean不能伸用在任何甘他地方
-
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person4" class="com.Person" p:age="4" p:name="Tommey周4"></bean>
<bean id="person3" class="com.Person">
<constructor-arg value="3" />
<constructor-arg value="Tommey3" index="1"/>
</bean>
<bean id="person5" class="com.Person">
<property name="age" value="4"></property>
<property name="name"><null /></property>
<!-- <property name="workerMan" ref="workerMan"> </property>-->
<!-- <property name="workerMan.job" value="架構師"> </property>-->
<!-- 內部bean -->
<property name="workerMan">
<bean class="com.WorkerMan">
<property name="job" value="高級工程師"></property>
<property name="sal" value="15092.33"></property>
</bean>
</property>
</bean>
<bean id="workerMan" class="com.WorkerMan">
<property name="job" value="程序員"></property>
<property name="sal" value="19999.8"></property>
</bean>
-
4)集合屬性
-
在Spring中可以通過一組內置的XML標籤來配置集合屬性,例如:<list>,<set>或<map>。
-
數組和List
- 配置java.util.List類型的屬性,需要指定<list>標籤,在標籤裏包含一些元素。
- 這些標籤 可以通過<value>指定簡單的常量值,通過<ref>指定對其他Bean的引用。
- 通過<bean>指定內置bean定義。通過<null/>指定空元素。甚至可以內嵌其他集合。
- 數組的定義和List一樣,都使用<list>元素。配置java.util.Set需要使用<set>標籤,定義的方法與List一樣。
<bean id="workerMan" class="com.WorkerMan">
<property name="job" value="程序員"></property>
<property name="sal" value="19999.8"></property>
<property name="level">
<list>
<value>A</value>
<value>B</value>
<value>C</value>
</list>
</property>
<property name="people">
<ref bean="person2" />
</property>
</bean>
-
Map
- Java.util.Map通過<map>標籤定義,<map>標籤裏可以使用多個<entry>作爲子標籤。
- 每個條目包含一個鍵和一個值。必須在<key>標籤裏定義鍵。因爲鍵和值的類型沒有限制,所以可以自由地爲它們指定<value>、<ref>、<bean>或<null/>元素。
- 可以將Map的鍵和值作爲<entry>的屬性定義:簡單常量使用key和value來定義;bean引用通過key-ref和value-ref屬性定義。
<bean id="workerMan" class="com.WorkerMan">
<property name="job" value="程序員"></property>
<property name="sal" value="19999.8"></property>
<property name="map">
<map>
<description>鍵值對</description>
<entry>
<key><value>1001</value></key>
<ref bean="person2" />
</entry>
</map>
</property>
</bean>
-
集合類型的bean
- 如果只能將集合對象配置在某個bean內部,則這個集合的配置將不能重用。我們需要 將集合bean的配置拿到外面,供其他bean引用。
- 配置集合類型的bean需要引入util名稱空間
<bean id="workerMan1" class="com.WorkerMan">
<property name="job" value="程序員"></property>
<property name="sal" value="19999.8"></property>
<property name="people" ref="persons"> </property>
</bean>
<util:list id="persons">
<ref bean="person"/>
<ref bean="person2"/>
<ref bean="person3"/>
</util:list>
-
5) FactoryBean
-
Spring中有兩種類型的bean,一種是普通bean,另一種是工廠bean,即FactoryBean。
-
工廠bean跟普通bean不同,其返回的對象不是指定類的一個實例,其返回的是該工廠bean的getObject方法所返回的對象。
-
工廠bean必須實現org.springframework.beans.factory.FactoryBean接口。
- 示例代碼:
- Car類:
public class Car {
private String brand;
private Double price;
}
- MyFactory類
public class MyFactory implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
Car car = new Car("奧迪",99999.99);
return car;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
- 配置類factory-bean.xml:
<?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="factory" class="com.MyFactory"></bean>
</beans>
- 測試類
@Test
public void demo02(){
ApplicationContext ac = new ClassPathXmlApplicationContext("factory-bean.xml");
Object factory = ac.getBean("factory");
System.out.println(factory);
}
-
6) bean的作用域
- 在Spring中,可以在<bean>元素的scope屬性裏設置bean的作用域,以決定這個bean是單實例的還是多實例的。
- 默認情況下,Spring只爲每個在IOC容器裏聲明的bean創建唯一一個實例,整個IOC容器範圍內都能共享該實例:所有後續的getBean()調用和bean引用都將返回這個唯一的bean實例。該作用域被稱爲singleton,它是所有bean的默認作用域。
類別 | 說明 |
---|---|
singleton | 在SpringIOC容器中僅存在一個Bean實例,Bean以單實例的方式存在 |
prototype | 每次調用 getBean() 時都會返回一個新的實例 |
request | 每次 HTTP 請求都會創建一個新的Bean,該作用域僅適用於WebApplicationContext環境 |
sesion | 同一個HTTP session 共享一個Bean,不同的HTTP Session 使用不同的Bean。該作用域僅適用於WebApplicationContext環境 |
-
當bean的作用域爲單例時,Spring會在IOC容器對象創建時就創建bean的對象實例。
-
而當bean的作用域爲prototype時,IOC容器在獲取bean的實例時創建bean的實例對象。
-
示例代碼:
<bean id="car" class="com.Car" scope="singleton">
<property name="brand" value="bmw"></property>
<property name="price" value="300000.22"></property>
</bean>
-
7) bean的生命週期
-
Spring IOC容器可以管理bean的生命週期,Spring允許在bean生命週期內特定的時間點執行指定的任務。
-
Spring IOC容器對bean的生命週期進行管理的過程:
①, 通過構造器或工廠方法創建bean實例
②, 爲bean的屬性設置值和對其他bean的引用
③, 調用bean的初始化方法
④ , 當容器關閉時,調用bean的銷燬方法
-
在配置bean時,通過init-method和destroy-method 屬性爲bean指定初始化和銷燬方法
-
bean的後置處理器
①, bean後置處理器允許在調用初始化方法前後對bean進行額外的處理
②, bean後置處理器對IOC容器裏的所有bean實例逐一處理,而非單一實例。其典型應用是:檢查bean屬性的正確性或根據特定的標準更改bean的屬性。
③, bean後置處理器需要實現接口:
org.springframework.beans.factory.config.BeanPostProcessor
。在初始化方法被調用前後,Spring將把每個bean實例分別傳遞給上述接口的以下兩個方法:●postProcessBeforeInitialization(Object, String)
●postProcessAfterInitialization(Object, String)
-
添加bean後置處理器後bean的生命週期
①,通過構造器或工廠方法創建bean實例
②,爲bean的屬性設置值和對其他bean的引用
③,將bean實例傳遞給bean後置處理器的postProcessBeforeInitialization()方法
④,調用bean的初始化方法
⑤,將bean實例傳遞給bean後置處理器的postProcessAfterInitialization()方法
⑥,當容器關閉時調用bean的銷燬方法
-
8)引用外部屬性文件
-
當bean的配置信息逐漸增多時,查找和修改一些bean的配置信息就變得愈加困難。這時可以將一部分信息提取到bean配置文件的外部,以properties格式的屬性文件保存起來,同時在bean的配置文件中引用properties屬性文件中的內容,從而實現一部分屬性值在發生變化時僅修改properties屬性文件即可。這種技術多用於連接數據庫的基本信息的配置。
-
直接配置
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="url" value="jdbc:mysql:///test"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
- 使用外部的屬性文件:
- 創建db.properties
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/test
jdbc.username = root
jdbc.password = root
- datasource.xml配置文件
<?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">
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 加載資源文件 -->
<!-- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">-->
<!-- <property name="location" value="db.properties"></property>-->
<!-- </bean>-->
<context:property-placeholder location="db.properties"/>
</beans>
- 測試
@Test
public void demo03() throws SQLException {
ApplicationContext ac = new ClassPathXmlApplicationContext("dataSource.xml");
DruidDataSource bean = ac.getBean("dataSource",DruidDataSource.class);
System.out.println(bean.getConnection());
}
-
9) 自動裝配
-
自動裝配的概念
-
手動裝配:以value或ref的方式
明確指定屬性值
都是手動裝配。 -
自動裝配:根據指定的裝配規則,
不需要明確指定
,Spring自動將匹配的屬性值注入bean中。
-
-
裝配模式:
-
①,
根據類型自動裝配
:將類型匹配的bean作爲屬性注入到另一個bean中。若IOC容器中有多個與目標bean類型一致的bean,Spring將無法判定哪個bean最合適該屬性,所以不能執行自動裝配 -
②,
根據名稱自動裝配
:必須將目標bean的名稱和屬性名設置的完全相同 -
③,
通過構造器自動裝配
:當bean中存在多個構造器時,此種自動裝配方式將會很複雜。不推薦使用。
-
-
選用建議
相對於使用註解的方式實現的自動裝配,在XML文檔中進行的自動裝配略顯笨拙,在項目中更多的使用註解的方式實現。
-
代碼實現
<!--
autowire:根據某種策略自動爲非字面量屬性賦值
byName:通過屬性名和spring容器中的bean的id進行比較,若一致則可直接賦值
byType:通過spring容器中bean的類型,爲兼容性的屬性賦值
在使用byType的過程中,要求spring容器中只能有一個能爲屬性賦值的bean
當設置autowire屬性,會作用於該bean中所有的非字面量屬性,因此誰都不用
-->
<bean id="person" class="com.Person" autowire="byType">
<property name="age" value="1"></property>
<property name="name" value="Tommey周"></property>
</bean>
<bean id="workerMan" class="com.WorkerMan">
<property name="sal" value="11111.11"></property>
<property name="job" value="中級工程師"></property>
</bean>
-
10)通過註解配置bean
-
概述
- 相對於XML方式而言,通過註解的方式配置bean更加簡潔和優雅,而且和MVC組件化開發的理念十分契合,是開發中常用的使用方式。
-
使用註解標識組件
-
①,普通組件:
@Component
標識一個受Spring IOC容器管理的組件
-
②,持久化層組件:
@Repository
標識一個受Spring IOC容器管理的持久化層組件
-
③,業務邏輯層組件:
@Service
標識一個受Spring IOC容器管理的業務邏輯層組件
-
④,表述層控制器組件:
@Controller
標識一個受Spring IOC容器管理的表述層控制器組件
-
⑤,組件命名規則
默認情況:使用組件的簡單類名首字母小寫後得到的字符串作爲bean的id
使用組件註解的value屬性指定bean的id
注意:事實上Spring並沒有能力識別一個組件到底是不是它所標記的類型,即使將
@Respository
註解用在一個表述層控制器組件上面也不會產生任何錯誤,所以@Respository、@Service、@Controller
這幾個註解僅僅是爲了讓開發人員自己明確 當前的組件扮演的角色。
-
-
代碼示例:
-
結構:
-
UserController類:
@Controller
public class UserController {
public UserController(){
System.out.println("UserController");
}
}
- UserService接口:
public interface UserService {
}
- 接口實現類UserServiceImpl:
@Service
public class UserServiceImpl implements UserService {
public UserServiceImpl(){
System.out.println("UserServiceImpl");
}
}
- UserDao接口:
public interface UserDao {
}
- 接口實現類UserDaoImpl:
@Repository
public class UserDaoImpl implements UserDao {
public UserDaoImpl(){
System.out.println("UserDaoImpl");
}
}
-
掃描組件
-
組件被上述註解標識後還需要通過Spring進行掃描才能夠偵測到。
- 指定被掃描的package
<context:component-scan base-package="com"/>
-
詳細說明
①,base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包及其子包中的所有類。
②,當需要掃描多個包時可以使用逗號分隔。
③,如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類,示例:
<context:component-scan base-package="com" resource-pattern="autowire/*.class"/>
④,包含與排除
<context:include-filter>
子節點表示要包含的目標類
注意:通常需要與use-default-filters屬性配合使用才能夠達到“僅包含某些 組件”這樣的效果。即:通過將use-default-filters屬性設置爲false,禁用默認過濾器,然後掃描的就只是include-filter中的規則指定的組件了。
-
<context:exclude-filter>
子節點表示要排除在外的目標類 -
component-scan
下可以擁有若干個include-filter和exclude-filter子節點 -
過濾表達式
類別 | 示例 | 說明 |
---|---|---|
annotation | com.XxxAnnotation | 過濾所有標註了XxxAnnotation的類。這個規則根據目標組件是否標註了指定類型的註解進行過濾。 |
assignable | com.BaseXxx | 過濾所有BaseXxx類的子類。這個規則根據目標組件是否是指定類型的子類的方式進行過濾。 |
aspectj | com.*Service+ | 所有類名是以Service結束的,或這樣的類的子類。這個規則根據AspectJ表達式進行過濾。 |
regex | com\.anno\.* | 所有com.anno包下的類。這個規則根據正則表達式匹配到的類名進行過濾。 |
custom | com.XxxTypeFilter | 使用XxxTypeFilter類通過編碼的方式自定義過濾規則。該類必須實現org.springframework.core.type.filter.TypeFilter接口 |
- 示例代碼:
<!--
<context:include-filter>:在設定的包結構下,再次通過註解或類型具體包含到某個或某幾個類
注意:在使用包含時,一定要設置use-default-filters="false",將默認的過濾(即掃描包下)關閉
-->
<context:component-scan base-package="com">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="assignable" expression="com.service.UserServiceImpl"/>
</context:component-scan>
-
一個
<context:component-scan>
中可以出現多個include,也可以同時出現多個exclue,但是這兩個不能同時出現 -
組件裝配
-
需求
Controller組件中往往需要用到Service組件的實例,Service組件中往往需要用到 Repository組件的實例。Spring可以通過註解的方式幫我們實現屬性的裝配。
-
-
基於註解的組件化管理:
@Component
,@Controller
(控制層),@Service
(業務層),Repository
(持久層),這四個註解功能完全相同,不過在實際開發中,要在實現不同功能的類上加上相應的註解 -
完成組件化管理的過程
①,在需要被spring管理的類上加上相應註解
②,在配置文件中通過
<context:component-scan>
對所設置的包結構進行掃描,就會將加上註解的類,作爲spring的組件進行加載-
實現依據
在指定要掃描的包時,
<context:component-scan>
元素會自動註冊一個bean的後置處 理器:AutowiredAnnotationBeanPostProcessor
的實例。該後置處理器可以自動裝配標記 了@Autowired、@Resource或@Inject註解的屬性。
-
-
@Autowired
註解①,
@Autowired
裝配時,會默認使用byType的方式,此時要求spring容器中只有一個能爲其賦值,當byType實現不了裝配時,會自動切換byName,此時要求spring容器中,有一個bean的id和屬性名一致。②,自動裝配:在需要賦值的非字面量屬性,加上
@Autowired
,就可以在spring容器中,通過不同的方式匹配到相應的bean,構造器、普通字段(即使是非public)、一切具有參數的方法都可以應用@Autowired
註解③,默認情況下,所有使用
@Autowired
註解的屬性都需要被設置。當Spring找不到匹 配的bean裝配屬性時,會拋出異常。④,若某一屬性允許不被設置,可以設置
@Autowired
註解的required屬性爲 false⑤,若自動裝配時,匹配到多給能夠賦值的bean,可使用
@Qualifier(value="beanId")
指定使用的bean,@Autowired
和@Qualifier(value="beanId")
可以一起作用域一個帶形參的方法上,此時@Qualifier(value="beanId")
所指定的bean作用於形參⑥,
@Autowired
註解也可以應用在數組類型的屬性上,此時Spring將會把所有匹配的bean進行自動裝配。⑦,
@Autowired
註解也可以應用在集合屬性上,此時Spring讀取該集合的類型信息,然後自動裝配所有與之兼容的bean。⑧,
@Autowired
註解用在java.util.Map上時,若該Map的鍵值爲String,那麼 Spring將自動裝配與值類型兼容的bean作爲值,並以bean的id值作爲鍵。 -
@Resource
@Resource
註解要求提供一個bean名稱的屬性,若該屬性爲空,則自動採用標註處的變量或方法名作爲bean的名稱。 -
@Inject
@Inject
和@Autowired
註解一樣也是按類型注入匹配的bean,但沒有reqired屬性。