原文鏈接http://zhhll.icu/2021/01/03/%E6%A1%86%E6%9E%B6/spring/spring%E9%85%8D%E7%BD%AEbean/
spring配置bean
使用xml配置
使用構造器創建
構造器創建bean是最常用的,如果不使用構造注入,Spring會呼叫無參構造器來創建實體
使用的是反射機制,要求該bean所對應的類必須有一個無參構造器
而對于注入方式,有構造器注入和setter方法注入
依賴注入方式
setter方法注入
使用setter方法注入時,注意一定要有無參構造器,spring會根據配置的class來使用class.newInstance()方法來實體化該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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置bean
class 配置bean的全類名,使用反射的方式創建bean,要求必須有一個無參構造器
id 標識容器z中的bean id唯一
-->
<bean id="helloWorld" >
<property name="name" value="https://www.cnblogs.com/life-time/p/Spring Hello"/>
</bean>
</beans>
注意:bean配置的property屬性的name值表示的是setter風格的屬性,即setter方法去掉set之后首字母小寫的名稱,并不是和成員變數進行對應
構造方法注入
<!--
value為屬性值
index 表示對應構造器的引數位置 從0開始
type 表示構造器該引數的型別
-->
<bean id="car" >
<constructor-arg value="https://www.cnblogs.com/life-time/p/法拉利" index="0"/>
<constructor-arg value="https://www.cnblogs.com/life-time/p/20000.0" type="double"/>
</bean>
獲取bean
// 創建spring的IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 從IOC容器獲取HelloWorld bean實體
HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
配置bean參考
如果bean之間有參考關系,可以使用ref來指定參考關系
public class Person {
private String name;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", car=" + car +
'}';
}
}
這里的ref中寫的是其他bean的id值
<bean id="car" >
<constructor-arg value="https://www.cnblogs.com/life-time/p/法拉利" index="0"/>
<constructor-arg value="https://www.cnblogs.com/life-time/p/20000.0" type="double"/>
</bean>
<bean id="person" >
<property name="name" value="https://www.cnblogs.com/life-time/p/張三"/>
<property name="car" ref="car"/>
</bean>
配置集合屬性
可以使用、
<bean id="person" >
<property name="name" value="https://www.cnblogs.com/life-time/p/張三"/>
<property name="car" ref="car"/>
<property name="cars">
<!-- list的示例 -->
<list>
<ref bean="car"/>
<ref bean="car2"/>
</list>
</property>
<property name="carMap">
<!-- map的示例 entry可以使用key/key-ref/value/value-ref -->
<map>
<entry key="AA" value-ref="car"/>
<entry key="BB" value-ref="car2"/>
</map>
</property>
</bean>
還有一種集合bean的方式,可以進行配置集合屬性
<!-- 配置集合bean -->
<util:list id="cars">
<ref bean="car"/>
<ref bean="car2"/>
</util:list>
然后在需要使用集合的bean中直接參考該集合bean
<bean id="person1" >
<property name="name" value="https://www.cnblogs.com/life-time/p/張三"/>
<property name="car" ref="car"/>
<!-- 參考上述定義的集合bean -->
<property name="cars" ref="cars"/>
</bean>
使用工廠bean來創建實際bean
可以提供一個實作FactoryBean介面的工廠bean來生產所實際需要的bean物件
/**
* 實作FactoryBean介面來生成car物件
* @author zh
* @date 2021/1/30 16:01
*/
public class CarFactoryBean implements FactoryBean<Car> {
/**
* 真正獲取物件的方法
* @return
* @throws Exception
*/
@Override
public Car getObject() throws Exception {
return new Car("瑪莎拉蒂",300);
}
/**
* 生成bean的型別
* @return
*/
@Override
public Class<?> getObjectType() {
return Car.class;
}
/**
* 是否是單例
* @return
*/
@Override
public boolean isSingleton() {
return true;
}
}
使用該factoryBean物件時,由于該bean實作了FactoryBean,所以spring不會把它作為一個普通的bean來處理,而是作為一個工廠bean,呼叫getObject()方法來創建實際需要的bean物件
<bean id="c" ></bean>
使用靜態工廠方法創建Bean
使用靜態工廠方法創建bean實體時,class屬性也必須指定,此時的class屬性并不是指定Bean實體的實作類,而是靜態工廠類,Spring通過該屬性知道由哪個工廠類來創建Bean實體,還可以使用factory-method屬性來指定靜態工廠方法,Spring將呼叫靜態工廠方法回傳一個Bean實體,靜態工廠方法需要引數的話,使用
public class StaticCarFactory {
private static Map<String,Car> cars = new HashMap<>();
static {
cars.put("aa",new Car("aa",300));
}
public static Car getCar(String name){
return cars.get(name);
}
}
<!-- 通過靜態工廠方法來配置bean
class 靜態工廠類
factory-method 靜態工廠方法的名字
constructor-arg 指定靜態方法的引數
-->
<bean id="car"
factory-method="getCar">
<constructor-arg name="name" value="https://www.cnblogs.com/life-time/p/aa" index="0"/>
</bean>
優點:將物件創建的程序封裝到靜態方法中,當客戶端需要物件時,只需要簡單地呼叫靜態方法,不需要關系創建物件的細節
呼叫實體工廠方法創建bean
實體工廠與靜態工廠只有一個不同,靜態工廠只需要使用工廠類即可,實體工廠需要工廠實體,使用factory-bean指定工廠實體
public class InstanceCarFactory {
private Map<String,Car> cars = null;
public InstanceCarFactory(){
cars = new HashMap<>();
cars.put("bb",new Car("bb", 30000.0));
}
public Car getCar(String name){
return cars.get(name);
}
}
<!-- 配置工廠實體 -->
<bean id="instanceCarFactory" />
<!-- 通過實體工廠方法來配置bean
factory-bean 實體工廠的bean
factory-method 實體工廠方法的名字
constructor-arg 指定方法的引數
-->
<bean id="car1" factory-bean="instanceCarFactory" factory-method="getCar">
<constructor-arg name="name" value="https://www.cnblogs.com/life-time/p/bb" index="0"/>
</bean>
自動裝配
上述的操作方式全是手動的進行注入的,如何進行自動裝配呢,可以使用autowire屬性來配置
<!-- 自動裝配 -->
<!-- byName 根據屬性名稱去匹配到對應的bean
byName 根據屬性的型別去匹配到對應的bean
-->
<bean id="testAutoWired" autowire="byName">
<property name="name" value="https://www.cnblogs.com/life-time/p/張三"/>
</bean>
如果使用byType,而且存在多個該型別的bean的話,就會出現例外
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.zhanghe.study.spring4.beans.beantest.Car' available: expected single matching bean but found 2: car,car2
使用注解配置
spring可以在classpath下進行組件掃描,包含注解有
- @Component 基本注解,表示是一個受spring管理的組件
- @Respository 表示持久層組件
- @Service 表示業務層組件
- @Controller 表示表現層組件
spring掃描到組件后,有默認的命名策略,將掃描到的類名進行首字母小寫,也可以在注解中使用value屬性值來標識組件的名稱
如果使用注解來標識bean的話,需要進行配置指定spring掃描的包,會掃描base-package指定的包及其子包
<context:component=scan base-package="包名"/>
使用注解進行配置
<!-- 設定包掃描路徑 -->
<context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest">
</context:component-scan>
還可以自定義的設定對于該包下的某些組件是否進行掃描
在使用<context:component=scan base-package="包名"/>標簽時,記得要加上context的命名空間
設定過濾
使用context:exclude-filter來設定排除哪些特定的組件
<context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest">
<!-- 使用context:exclude-filter來設定排除哪些特定的組件
type annotation表示使用注解的運算式
assignable保護指定具體bean的類名
-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
設定包含
使用context:include-filter來設定只掃描哪些特定的組件
<context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest" use-default-filters="false">
<!-- 使用context:include-filter來設定只掃描哪些特定的組件,如果使用include-filter的話需要設定use-default-filters="false" -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
自動裝配
使用xml進行自動裝配的時候略顯笨拙,而且使用起來也并不順心,因為autowire只能選擇byName或者byType,如果存在多個相同型別的bean使用byType就會出現問題,大家可能因此想要放棄自動裝配,其實自動裝配與注解搭配起來還是很好用的,下面來了解一下
如果bean與bean之間如在關聯關系,如在beanA中需要呼叫beanB的方法,如何來獲取beanB中的實體呢
<context:component-scan>元素會自動注冊AutowiredAnnotationBeanPostProcessor實體,該實體可以自動裝配具有@AutoWired、@Resource和@Inject注解的屬性
@Autowired默認使用byType,如果存在型別相同的兩個bean,則使用byName來根據屬性的名稱來匹配bean
@Resource注解是使用的byName,需要提供bean的名稱,如果不提供該bean的名稱,則自動使用屬性的名稱進行匹配
@Inject與@AutoWired一樣,只是沒有required屬性
-
使用@Autowired 和@Qualifier結合來明確指定需要裝配的Bean
@Autowired @Qualifier("bpmServiceImpl") private BpmService bpmService; -
使用@Inject和@Named結合來指定
@Inject @Named("compensateServiceImpl") private CompensateService compensateService;
由于本身的博客百度沒有收錄,博客地址http://zhhll.icu
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/262353.html
標籤:Java
