spring配置bean

原文連接http://zhhll.icu/2021/01/03/%E6%A1%86%E6%9E%B6/spring/spring%E9%85%8D%E7%BD%AEbean/java

spring配置bean

使用xml配置

使用構造器建立

構造器建立bean是最經常使用的,若是不使用構造注入,Spring會調用無參構造器來建立實例spring

使用的是反射機制,要求該bean所對應的類必須有一個無參構造器express

而對於注入方式,有構造器注入和setter方法注入ide

依賴注入方式
setter方法注入

使用setter方法注入時,注意必定要有無參構造器,spring會根據配置的class來使用class.newInstance()方法來實例化該beanui

<?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" class="com.zhanghe.study.spring4.beans.helloworld.HelloWorld">
        <property name="name" value="Spring Hello"/>
    </bean>
</beans>

注意:bean配置的property屬性的name值表示的是setter風格的屬性,即setter方法去掉set以後首字母小寫的名稱,並非和成員變量進行對應this

構造方法注入
<!-- 
	value爲屬性值
 	index 表示對應構造器的參數位置  從0開始
	type 表示構造器該參數的類型
-->
<bean id="car" class="com.zhanghe.study.spring4.beans.beantest.Car">
  <constructor-arg value="法拉利" index="0"/>
  <constructor-arg value="20000.0" type="double"/>
</bean>

獲取beanspa

// 建立spring的IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 從IOC容器獲取HelloWorld  bean實例
HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
配置bean引用

若是bean之間有引用關係,可使用ref來指定引用關係code

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值component

<bean id="car" class="com.zhanghe.study.spring4.beans.beantest.Car">
  <constructor-arg value="法拉利" index="0"/>
  <constructor-arg value="20000.0" type="double"/>
</bean>

<bean id="person" class="com.zhanghe.study.spring4.beans.beantest.Person">
  <property name="name" value="張三"/>
  <property name="car" ref="car"/>
</bean>
配置集合屬性

可使用 來對集合屬性賦值 xml

<bean id="person" class="com.zhanghe.study.spring4.beans.beantest.Person">
  <property name="name" value="張三"/>
  <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" class="com.zhanghe.study.spring4.beans.beantest.Person">
    <property name="name" value="張三"/>
    <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" class="com.zhanghe.study.spring4.beans.beantest.CarFactoryBean"></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" class="com.zhanghe.study.spring4.beans.beantest.StaticCarFactory"
      factory-method="getCar">
  <constructor-arg name="name" value="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" 	class="com.zhanghe.study.spring4.beans.beantest.InstanceCarFactory"/>

<!-- 經過實例工廠方法來配置bean
  factory-bean 實例工廠的bean
  factory-method 實例工廠方法的名字
  constructor-arg 指定方法的參數
-->
<bean id="car1" factory-bean="instanceCarFactory" factory-method="getCar">
	<constructor-arg name="name" value="bb" index="0"/>
</bean>

自動裝配

上述的操做方式全是手動的進行注入的,如何進行自動裝配呢,可使用autowire屬性來配置

<!-- 自動裝配 -->
<!-- byName 根據屬性名稱去匹配到對應的bean
		 byName  根據屬性的類型去匹配到對應的bean
-->
<bean id="testAutoWired" class="com.zhanghe.study.spring4.beans.beantest.Person" autowire="byName">
    <property name="name" value="張三"/>
</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

相關文章
相關標籤/搜索