1. 程式人生 > >Spring入門及bean配置(XML、註解)

Spring入門及bean配置(XML、註解)

目錄

一、概述

一、概述

Spring是一個開放原始碼的設計層面框架,他解決的是業務邏輯層和其他各層的鬆耦合問題,因此它將面向介面的程式設計思想貫穿整個系統應用。Spring是於2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson建立。簡單來說,Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源框架(摘自:百度百科)

二、bean與spring容器的關係

Bean配置資訊定義了Bean的實現及依賴關係,Spring容器根據各種形式的Bean配置資訊在容器內部建立Bean定義登錄檔,然後根據登錄檔載入、例項化Bean,並建立Bean和Bean的依賴關係,最後將這些準備就緒的Bean放到Bean快取池中,以供外層的應用程式進行呼叫。

三、bean配置

bean配置有三種方法:

  • 基於xml配置Bean
  • 使用註解定義Bean
  • 基於java類提供Bean定義資訊

3.1 基於xml配置Bean

 對於基於XML的配置,Spring 2.0以後使用Schema的格式,使得不同型別的配置擁有了自己的名稱空間,是配置檔案更具擴充套件性。

①預設名稱空間:它沒有空間名,用於Spring Bean的定義;

②xsi名稱空間:這個名稱空間用於為每個文件中名稱空間指定相應的Schema樣式檔案,是標準組織定義的標準名稱空間;

③aop名稱空間:這個名稱空間是Spring配置AOP的名稱空間,是使用者自定義的名稱空間。

名稱空間的定義分為兩個步驟:第一步指定名稱空間的名稱;第二步指定名稱空間的Schema文件樣式檔案的位置,用空格或回車換行進行分分隔。

3.1.1 Bean基本配置

在Spring容器的配置檔案中定義一個簡要Bean的配置片段如下所示:

一般情況下,Spring IOC容器中的一個Bean即對應配置檔案中的一個<bean>,這種映象對應關係應該容易理解。其中id為這個Bean的名稱,通過容器的getBean("foo")即可獲取對應的Bean,在容器中起到定位查詢的作用,是外部程式和Spring IOC容器進行互動的橋樑。class屬性指定了Bean對應的實現類。

下面是基於XML的配置檔案定義了兩個簡單的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-3.0.xsd">
     <bean id="car" name="#car1" class="com.baobaotao.simple.Car"></bean>  
     <bean id="boss" class="com.baobaotao.simple.Boss"></bean>
</beans>

3.1.2 依賴注入

  1. 屬性注入
  2. 建構函式注入
  3. 工廠方式注入

3.2 使用註解定義Bean

我們知道,Spring容器成功啟動的三大要件分別是:Bean定義資訊、Bean實現類以及Spring本身。如果採用基於XML的配置,Bean定義資訊和Bean實現類本身是分離的,而採用基於註解的配置方式時,Bean定義資訊即通過在Bean實現類上標註註解實現。

下面是使用註解定義一個DAO的Bean:

package com.baobaotao.anno;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
//①通過Repository定義一個DAO的Bean

@Component("userDao")
public class UserDao {

}

在①處,我們使用@Component註解在UserDao類宣告處對類進行標註,它可以被Spring容器識別,Spring容器自動將POJO轉換為容器管理的Bean。

它和以下的XML配置是等效的:

<bean id="userDao" class="com.baobaotao.anno.UserDao"/>

除了@Component以外,Spring提供了3個功能基本和@Component等效的註解,它們分別用於對DAO、Service及Web層的Controller進行註解,所以也稱這些註解為Bean的衍型註解:(類似於xml檔案中定義Bean<bean id=" " class=" "/>

  • @Repository:用於對DAO實現類進行標註;
  • @Service:用於對Service實現類進行標註;
  • @Controller:用於對Controller實現類進行標註;

之所以要在@Component之外提供這三個特殊的註解,是為了讓註解類本身的用途清晰化,此外Spring將賦予它們一些特殊的功能。

3.2.1 使用註解配置資訊啟動spring容器

Spring提供了一個context的名稱空間,它提供了通過掃描類包以應用註解定義Bean的方式:

<?xml version="1.0" encoding="UTF-8" ?>
<!--①宣告context的名稱空間-->
<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-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd"
         >
    <!--②掃描類包以應用註解定義的Bean-->
   <context:component-scan base-package="com.baobaotao.anno"/>
   <bean class="com.baobaotao.anno.LogonService"></bean>
   <!-- context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ -->
   <!-- context:component-scan base-package="com.baobaotao">
       <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Dao"/>
       <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Service"/>
       <context:exclude-filter type="aspectj" expression="com.baobaotao..*Controller+"/>
   </context:component-scan -->
</beans>

在①處宣告context名稱空間,在②處即可通過context名稱空間的component-scan的base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包裡的所有類,並從類的註解資訊中獲取Bean的定義資訊。

如果僅希望掃描特定的類而非基包下的所有類,你們可以使用resource-pattern屬性過濾特定的類,如下所示:

<context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/>

這裡我們將基類包設定為com.baobaotao,預設情況下resource-pattern屬性的值為"**/*.class",即基類包裡的所有類。這裡我們設定為"anno/*.class",則Spring僅會掃描基包裡anno子包中的類。

3.3 基於java類提供Bean定義

在普通的POJO類中只要標註@Configuration註解,就可以為spring容器提供Bean定義的資訊了,每個標註了@Bean的類方法都相當於提供了一個Bean的定義資訊。

package com.baobaotao.conf;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//①將一個POJO標註為定義Bean的配置類
@Configuration
public class AppConf {
        //②以下兩個方法定義了兩個Bean,以提供了Bean的例項化邏輯
    @Bean
    public UserDao userDao(){
       return new UserDao();    
    }
    
    @Bean
    public LogDao logDao(){
        return new LogDao();
    }
    //③定義了logonService的Bean
    @Bean
    public LogonService logonService(){
        LogonService logonService = new LogonService();
                //④將②和③處定義的Bean注入到LogonService Bean中
        logonService.setLogDao(logDao());
        logonService.setUserDao(userDao());
        return logonService;
    }
}

①處在APPConf類的定義處標註了@Configuration註解,說明這個類可用於為Spring提供Bean的定義資訊。類的方法處可以標註@Bean註解,Bean的型別由方法返回值型別決定,名稱預設和方法名相同,也可以通過入參顯示指定Bean名稱,如@Bean(name="userDao").直接在@Bean所標註的方法中提供Bean的例項化邏輯。

在②處userDao()和logDao()方法定義了一個UserDao和一個LogDao的Bean,它們的Bean名稱分別是userDao和logDao。在③處,又定義了一個logonService Bean,並且在④處注入②處所定義的兩個Bean。

因此,以上的配置和以下XML配置時等效的:

<bean id="userDao" class="com.baobaotao.anno.UserDao"/>
<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
<bean id="logService" class="com.baobaotao.conf.LogonService"
    p:logDao-ref="logDao" p:userDao-ref="userDao"/>

基於java類的配置方式和基於XML或基於註解的配置方式相比,前者通過程式碼的方式更加靈活地實現了Bean的例項化及Bean之間的裝配,但後面兩者都是通過配置宣告的方式,在靈活性上要稍遜一些,但是配置上要更簡單一些。

四、Bean注入

Bean注入的方式有兩種,一種是在XML中配置,此時分別有屬性注入、建構函式注入和工廠方法注入;另一種則是使用註解的方式注入 @Autowired,@Resource,@Required

4.1 在xml檔案中配置依賴注入

4.1.1 屬性注入

屬性注入即通過setXxx()方法注入Bean的屬性值或依賴物件,由於屬性注入方式具有可選擇性和靈活性高的優點,因此屬性注入是實際應用中最常採用的注入方式。

屬性注入要求Bean提供一個預設的建構函式,併為需要注入的屬性提供對應的Setter方法。Spring先呼叫Bean的預設建構函式例項化Bean物件,然後通過反射的方式呼叫Setter方法注入屬性值。

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware;

public class LogonService implements BeanNameAware{

    private LogDao logDao;

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void setLogDao(LogDao logDao) {
        this.logDao = logDao;
    }
    
    public LogDao getLogDao() {
        return logDao;
    }
    public UserDao getUserDao() {
        return userDao;
    }
    
    public void setBeanName(String beanName) {
        System.out.println("beanName:"+beanName);        
    }
    
    public void initMethod1(){
        System.out.println("initMethod1");
    }
    public void initMethod2(){
        System.out.println("initMethod2");
    }
    
}

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" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd"
       default-autowire="byName"
         >
    <bean id="logDao" class="com.baobaotao.anno.LogDao"/>
    <bean id="userDao" class="com.baobaotao.anno.UserDao"/>
   <bean class="com.baobaotao.anno.LogonService">
       <property name="logDao" ref="logDao"></property>
       <property name="userDao" ref="userDao"></property>
   </bean>
</beans>

4.1.2 構造方法注入

使用建構函式注入的前提是Bean必須提供帶引數的建構函式。例如

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware;

public class LogonService implements BeanNameAware{

    public LogonService(){}

    public LogonService(LogDao logDao, UserDao userDao) {
        this.logDao = logDao;
        this.userDao = userDao;
    }

    private LogDao logDao;

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void setLogDao(LogDao logDao) {
        this.logDao = logDao;
    }
    
    public LogDao getLogDao() {
        return logDao;
    }
    public UserDao getUserDao() {
        return userDao;
    }
    
    public void setBeanName(String beanName) {
        System.out.println("beanName:"+beanName);        
    }
    
    public void initMethod1(){
        System.out.println("initMethod1");
    }
    public void initMethod2(){
        System.out.println("initMethod2");
    }
    
}

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" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd"
       default-autowire="byName">

    <bean id="logDao" class="com.baobaotao.anno.LogDao"/>
    <bean id="userDao" class="com.baobaotao.anno.UserDao"/>
   <bean class="com.baobaotao.anno.LogonService">
      <constructor-arg  ref="logDao"></constructor-arg>
       <constructor-arg ref="userDao"></constructor-arg>
   </bean>

</beans>

4.1.3 工廠方法注入

非靜態工廠方法:

有些工廠方法是非靜態的,即必須例項化工廠類後才能呼叫工廠放。

package com.baobaotao.ditype;

public class CarFactory {
   public Car createHongQiCar(){
       Car car = new Car();
       car.setBrand("紅旗CA72");
       return car;
   }
   
   public static Car createCar(){
       Car car = new Car();
       return car;
   }
}

工廠類負責建立一個或多個目標類例項,工廠類方法一般以介面或抽象類變數的形式返回目標類例項,工廠類對外遮蔽了目標類的例項化步驟,呼叫者甚至不用知道具體的目標類是什麼。

<?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-3.0.xsd">

    <!-- 工廠方法-->
    <bean id="carFactory" class="com.baobaotao.ditype.CarFactory" />
    <bean id="car5" factory-bean="carFactory" factory-method="createHongQiCar">
    </bean>


</beans>

靜態工廠方法:

很多工廠類都是靜態的,這意味著使用者在無須建立工廠類例項的情況下就可以呼叫工廠類方法,因此,靜態工廠方法比非靜態工廠方法的呼叫更加方便。

<?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-3.0.xsd">

    <bean id="car6" class="com.baobaotao.ditype.CarFactory"
        factory-method="createCar"></bean>

</beans>

4.2 使用註解的方式注入

4.2.1 使用@Autowired進行自動注入

Spring通過@Autowired註解實現Bean的依賴注入,下面是一個例子:

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
//① 定義一個Service的Bean(不需要在XML中定義Bean)
@Service
public class LogonService implements BeanNameAware{
        //② 分別注入LogDao及UserDao的Bean(不需要在XML中定義property屬性注入)
    @Autowired(required=false)
    private LogDao logDao;
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;
    
    public LogDao getLogDao() {
        return logDao;
    }
    public UserDao getUserDao() {
        return userDao;
    }
    
    public void setBeanName(String beanName) {
        System.out.println("beanName:"+beanName);        
    }
    
    public void initMethod1(){
        System.out.println("initMethod1");
    }
    public void initMethod2(){
        System.out.println("initMethod2");
    }
    
}
 

在①處,我們使用@Service將LogonService標註為一個Bean,在②處,通過@Autowired注入LogDao及UserDao的Bean。@Autowired預設按型別匹配的方式,在容器查詢匹配的Bean,當有且僅有一個匹配的Bean時,Spring將其注入到@Autowired標註的變數中。

4.2.2 使用@Autowired的required屬性

如果容器中沒有一個和標註變數型別匹配的Bean,Spring容器啟動時將報NoSuchBeanDefinitionException的異常。如果希望Spring即使找不到匹配的Bean完成注入也不用丟擲異常,那麼可以使用@Autowired(required=false)進行標註:

@Service
public class LogonService implements BeanNameAware{
    @Autowired(required=false)
    private LogDao logDao;
        ...
}

預設情況下,@Autowired的required屬性的值為true,即要求一定要找到匹配的Bean,否則將報異常。

4.2.3 使用@Qualifier指定注入Bean的名稱

如果容器中有一個以上匹配的Bean時,則可以通過@Qualifier註解限定Bean的名稱,如下所示:

@Service
public class LogonService implements BeanNameAware{
    @Autowired(required=false)
    private LogDao logDao;
    //①注入名為UserDao,型別為UserDao的Bean
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;
}

這裡假設容器有兩個型別為UserDao的Bean,一個名為userDao,另一個名為otherUserDao,則①處會注入名為userDao的Bean。

4.2.4 對類方法進行標註

@Autowired可以對類成員變數及方法的入參進行標註,下面我們在類的方法上使用@Autowired註解:

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class LogonService implements BeanNameAware{
    
    private LogDao logDao;
    private UserDao userDao;
    
    
    @Autowired
    public void setLogDao(LogDao logDao) {
        this.logDao = logDao;
    }
    
    @Autowired
    @Qualifier("userDao")
    public void setUserDao(UserDao userDao) {
        System.out.println("auto inject");
        this.userDao = userDao;
    }
    
}

如果一個方法擁有多個入參,在預設情況下,Spring自動選擇匹配入參型別的Bean進行注入。Spring允許對方法入參標註@Qualifier以指定注入Bean的名稱,如下所示:

@Autowired
public void init(@Qualifier("userDao")UserDao userDao,LogDao logDao){
    System.out.println("multi param inject");
    this.userDao = userDao;
    this.logDao =logDao;
}

在以上例子中,UserDao的入參注入名為userDao的Bean,而LogDao的入參注入LogDao型別的Bean。

一般情況下,在Spring容器中大部分的Bean都是單例項的,所以我們一般都無須通過@Repository、@Service等註解的value屬性為Bean指定名稱,也無須使用@Qualifier按名稱進行注入。

4.2.5 對標準註解的支援

此外,Spring還支援@Resource和@Inject註解,這兩個標準註解和@Autowired註解的功能型別,都是對類變數及方法入參提供自動注入的功能。@Resource要求提供一個Bean名稱的屬性,如果屬性為空,則自動採用標註處的變數名或方法名作為Bean的名稱。


package com.baobaotao.anno;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component
public class Boss {
    
    private Car car;
    
    public Boss(){
        System.out.println("construct...");
    }

//    @Autowired
//    private void setCar(Car car){
//        System.out.println("execute in setCar");
//        this.car = car;
//    }
    
    @Resource("car")
    private void setCar(Car car){
        System.out.println("execute in setCar");
        this.car = car;
    }
    
    @PostConstruct
    private void init1(){
        System.out.println("execute in init1");
    }
    
    @PostConstruct
    private void init2(){
        System.out.println("execute in init1");
    }
    
    @PreDestroy
    private void destory1(){
        System.out.println("execute in destory1");
    }
    
    @PreDestroy
    private void destory2(){
        System.out.println("execute in destory2");
    }

}

這時,如果@Resource未指定"car"屬性,則也可以根據屬性方法得到需要注入的Bean名稱。可見@Autowired預設按型別匹配注入Bean,@Resource則按名稱匹配注入Bean。而@Inject和@Autowired一樣也是按型別匹配注入的Bean的,只不過它沒有required屬性。可見不管是@Resource還是@Inject註解,其功能都沒有@Autowired豐富,因此除非必須,大可不必在乎這兩個註解。(類似於Xml中使用<constructor-arg ref="logDao"></constructor-arg>或者<property name="logDao" ref="logDao"></property>進行注入,如果使用了@Autowired或者Resource等,這不需要在定義Bean時使用屬性注入和構造方法注入了)

4.2.6 關於Autowired和@Resource

[email protected]注入是按照型別注入的,只要配置檔案中的bean型別和需要的bean型別是一致的,這時候注入就沒問題。但是如果相同型別的bean不止一個,此時注入就會出現問題,Spring容器無法啟動。 
[email protected]標籤是按照bean的名字來進行注入的,如果我們沒有在使用@Resource時指定bean的名字,同時Spring容器中又沒有該名字的bean,這時候@Resource就會退化為@Autowired即按照型別注入,這樣就有可能違背了使用@Resource的初衷。所以建議在使用@Resource時都顯示指定一下bean的名字@Resource(name="xxx") 

4.2.7 讓@Resource和@Autowired生效的幾種方式

1.在xml配置檔案中顯式指定 

<!-- 為了使用Autowired標籤,我們必須在這裡配置一個bean的後置處理器 -->  
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />   
      
<!-- 為了使用@Resource標籤,這裡必須配置一個後置處理器 -->  
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />   

2.在xml配置檔案中使用context:annotation-config 

<context:annotation-config />

3.在xml配置檔案中使用context:component-scan 

<context:component-scan base-package="com.baobaotao.anno"/>

4.重寫Spring容器的Context,在自定義BeanFactory時呼叫AnnotationConfigUtils.registerAnnotationConfigProcessors()把這兩個註解處理器增加到容器中。 

一開始使用公司框架的時候發現可以在web層使用@Resource以及@Autowired來注入一些bean,首先這個註解是Spring提供的,自己把這部分程式碼抽出來寫了小例子,發現要想使用Spring的這兩註解,必須直接或者間接的引入AutowiredAnnotationBeanPostProcesso以及CommonAnnotationBeanPostProcessor這兩個註解處理器引入到BeanDefinitions中,否則不會實現注入的,但是仔細閱讀公司框架程式碼後發現沒有地方直接或間接引入這兩個註解處理器,發現一個細節,公司框架所依賴的Spring版本是2.5.6而我使用的Spring版本是2.5.5,當初的結論是高版本的Spring在容器啟動的時候,自動把這兩個註解處理器加入到BeanDefinitions中,這幾天仔細看了看Spring的原始碼,發現Spring2.5.6並沒有這樣做。然後子寫DEBUG了一下公司框架的原始碼,最後發現原來公司框架有一個自己的XmlWebApplicationContext,在這個context中重寫customizeBeanFactory(),在這個方法中呼叫了AnnotationConfigUtils.registerAnnotationConfigProcessors()方法把這兩自動註解處理器加入到BeanDefinitions中,這樣公司框架在web層就支援@Resource和@Autowired進行自動注入啦 


//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.alibaba.citrus.springext.support.context;

import com.alibaba.citrus.springext.ResourceLoadingExtendable;
import com.alibaba.citrus.springext.ResourceLoadingExtender;
import com.alibaba.citrus.springext.support.context.InheritableListableBeanFactory;
import com.alibaba.citrus.springext.support.resolver.XmlBeanDefinitionReaderProcessor;
import java.io.IOException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;

public class XmlWebApplicationContext extends org.springframework.web.context.support.XmlWebApplicationContext implements ResourceLoadingExtendable {
    private ResourceLoadingExtender resourceLoadingExtender;
    private boolean parentResolvableDependenciesAccessible = true;

    public XmlWebApplicationContext() {
    }

    public boolean isParentResolvableDependenciesAccessible() {
        return this.parentResolvableDependenciesAccessible;
    }

    public void setParentResolvableDependenciesAccessible(boolean parentResolvableDependenciesAccessible) {
        this.parentResolvableDependenciesAccessible = parentResolvableDependenciesAccessible;
    }

    public void setResourceLoadingExtender(ResourceLoadingExtender resourceLoadingExtender) {
        if(this.resourceLoadingExtender != null) {
            this.getApplicationListeners().remove(this.resourceLoadingExtender);
        }

        this.resourceLoadingExtender = resourceLoadingExtender;
        if(resourceLoadingExtender instanceof ApplicationListener) {
            this.addApplicationListener((ApplicationListener)resourceLoadingExtender);
        }

    }

    protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
        (new XmlBeanDefinitionReaderProcessor(beanDefinitionReader)).addConfigurationPointsSupport();
    }

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        super.customizeBeanFactory(beanFactory);
    //AnnotationConfigUtils.registerAnnotationConfigProcessors()方法把這兩自動註解處理器加入到BeanDefinitions中,這樣公司框架在web層就支援@Resource和@Autowired進行自動注入
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory, (Object)null);
    }

    protected DefaultListableBeanFactory createBeanFactory() {
        return (DefaultListableBeanFactory)(this.isParentResolvableDependenciesAccessible()?new InheritableListableBeanFactory(this.getInternalParentBeanFactory()):super.createBeanFactory());
    }

    protected Resource getResourceByPath(String path) {
        Resource resource = null;
        if(this.resourceLoadingExtender != null) {
            resource = this.resourceLoadingExtender.getResourceByPath(path);
        }

        if(resource == null) {
            resource = super.getResourceByPath(path);
        }

        return resource;
    }

    protected ResourcePatternResolver getResourcePatternResolver() {
        final ResourcePatternResolver defaultResolver = super.getResourcePatternResolver();
        return new ResourcePatternResolver() {
            public Resource[] getResources(String locationPattern) throws IOException {
                ResourcePatternResolver resolver = null;
                if(XmlWebApplicationContext.this.resourceLoadingExtender != null) {
                    resolver = XmlWebApplicationContext.this.resourceLoadingExtender.getResourcePatternResolver();
                }

                if(resolver == null) {
                    resolver = defaultResolver;
                }

                return resolver.getResources(locationPattern);
            }

            public ClassLoader getClassLoader() {
                return defaultResolver.getClassLoader();
            }

            public Resource getResource(String location) {
                return defaultResolver.getResource(location);
            }
        };
    }
}

相關推薦

Spring入門bean配置XML註解

目錄 一、概述 一、概述 Spring是一個開放原始碼的設計層面框架,他解決的是業務邏輯層和其他各層的鬆耦合問題,因此它將面向介面的程式設計思想貫穿整個系統應用。Spring是於2003

bean配置的三種方式XML註解Java類介紹與對比

如此的話,我們便不在需要在XML當中顯式使用bean來進行bean的配置。Spring容器在初始化的時候便會自動掃描base-package所指定的包以及子包下面的所有class檔案。所有標註為Repository的類將被自動註冊為bean。

httpd安裝和配置cgiwsgi

參考:http://webpy.org/cookbook/mod_wsgi-apache.zh-cn   一、yum方式安裝: 1、yum install httpd 輸入y後繼續。   2、看到一下類似的返回,說明安裝成功 &n

mysql5.7 yum安裝主從配置從庫只讀,不重啟主庫新增從庫配置

yum -y remove mysql wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm rpm -ivh mysql57-community-release-el7-8.noarch.rpm yum -y ins

Spring AOP切面優先順序XML註解

【Spring4.0筆記整理十四】AOP切面優先順序(XML和註解) - CSDN部落格 https://blog.csdn.net/sun8112133/article/details/80551886     我們常常會遇到這樣一個問題, 如果有兩個或多個切面同時對應同一個

activiti根據流程例項id查詢資原始檔xmlimage

/** * 讀取資源,通過部署ID * * @param processDefinitionId * 流程定義 * @param resourceType * 資源型別(xml|image) * @throws Exception */ @

使用XStream註解處理複雜xml的屬性資料集合xml轉物件

1. XStream簡介 2.簡單使用 <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactI

spring多資料來源的配置分散式事務管理

<bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResource

Django 數據庫連接配置OracleMysql

配置 ons mode base acl name mman xxx word 一、Django Oracle連接配置 DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.oracle‘, ‘NAME‘: ‘D

spring mvc異常統一處理使用ControllerAdvice註解

1、配置 spring 版本: [html] view plain copy print? <org.springframework-version>4.1.9.RELEASE</org.springframework-version>

【初識Spring】物件Bean例項化屬性注入xml方式

初識Spring之Bean例項化及屬性注入 1.通過xml配置的方式進行例項化。 - 配置檔案中bean標籤的常用屬性 - 通過無參構造(常用) - 使用靜態工廠進行建立 - 使用例項工廠進行建立 2.屬性注入。 - 使用有引數構造方法注入屬性

Spring Data Redis入門示例:程序配置

dex port scl lis fault gre source inf 操作 單機配置 redis.properties配置 #redis的服務器地址 redis.host=127.0.0.1 #redis的服務端口 redis.port=6379 #客戶端超時時間

項目中 Spring 配置文件的選型問題 xml註解的抉擇

color 比較 選型 文件中 場景 簡潔 管理 項目組 col 要改的東西用xml 不改的東西用註解;這句是對用不用註解或者 xml的一個不錯的解決方案 xml使用場景: 1.外部jar包依賴bean配置 2.用註解無法實現,或者

Spring筆記三】SpringBeanXML方式裝配

       我們可以把 Spring 看作一個大型的工廠,而 Spring 容器中的 Bean 就是該工廠的產品。要想使用這個工廠生產和管理Bean,就需要在配置檔案中告訴它需要哪些 Be

JAVA WEB快速入門之通過一個簡單的Spring專案瞭解Spring的核心AOPIOC

接上篇《JAVA WEB快速入門之從編寫一個JSP WEB網站了解JSP WEB網站的基本結構、除錯、部署》,通過一個簡單的JSP WEB網站了解了JAVA WEB相關的知識,比如:Servlet、Fitler、Listner等,這為後面搭建基於SSM的框架奠定了基礎知識,當然光了解JSP相關的知識還不行,我

ELKStack分散式日誌查詢分析伺服器安裝配置ElasticSearchLogstashKibanaRedis

ELK對於沒有接觸的來說,並沒有一般的服務那麼容易安裝和使用,不過也沒有那麼難,elk一般作為日誌分析套裝工具使用。logs由logstash輸 入,logstash通過配置檔案對日誌做過濾、匹配,就是用來分析日誌的,輸出到elasticsearch,所以他的配置需要和日誌相匹配。 elas

SpringBean管理XML方式&屬性注入

1、Spring對Bean的例項化方式 Bean已經都交給Spring進行管理,Spring在建立這些類的時候,有三種方式 1.1 無參構造方法的方式(預設) 編寫類 public class Bean1{ public void Bean1(){ super();

複習之spring基礎——Spring 的事務管理—配置AOP事務XML註解方式

事務 事務邏輯上的一組操作,組成這組操作的各個邏輯單元,要麼一起成功,要麼一起失敗 事務的特性 原子性 :強調事務的不可分割. 一致性 :事務的執行的前後資料的完整性保持一致. 隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾. 永續性 :事務一旦結束

Spring 學習——Spring 中的 Bean 配置

配置形式:基於 XML 檔案的方式;基於註解的方式 Bean 的配置方式:通過全類名(反射)、通過工廠方法(靜態工廠方法 & 例項工廠方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依賴注入

Spring Boot + Spring Cloud 實現許可權管理系統 後端篇二十三配置中心ConfigBus

線上演示 使用者名稱:admin 密碼:admin 技術背景 如今微服務架構盛行,在分散式系統中,專案日益龐大,子專案日益增多,每個專案都散落著各種配置檔案,且隨著服務的增加而不斷增多。此時,往往某一個基礎服務資訊變更,都會導致一系列服務的更新和重啟,運維也是苦不堪言,而且還很容易出錯。於是,配置中心便由此