spring中bean配置和bean注入

1 bean与spring容器的关系

Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。

1 bean配置

bean配置有三种方法:

  • 基于xml配置Bean
  • 使用注解定义Bean
  • 基于java类提供Bean定义信息

1.1 基于xml配置Bean

 对于基于XML的配置,Spring 2.0以后使用Schema的格式,使得不同类型的配置拥有了自己的命名空间,是配置文件更具扩展性。

①默认命名空间:它没有空间名,用于Spring Bean的定义;

②xsi命名空间:这个命名空间用于为每个文档中命名空间指定相应的Schema样式文件,是标准组织定义的标准命名空间;

③aop命名空间:这个命名空间是Spring配置AOP的命名空间,是用户自定义的命名空间。

 

命名空间的定义分为两个步骤:第一步指定命名空间的名称;第二步指定命名空间的Schema文档样式文件的位置,用空格或回车换行进行分分隔。

1.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>

1.1.2 依赖注入

  1. 属性注入
  2. 构造函数注入
  3. 工厂方式注入

1.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将赋予它们一些特殊的功能。

1.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子包中的类。

1.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之间的装配,但后面两者都是通过配置声明的方式,在灵活性上要稍逊一些,但是配置上要更简单一些。

 2 Bean注入

Bean注入的方式有两种,一种是在XML中配置,此时分别有属性注入、构造函数注入和工厂方法注入;另一种则是使用注解的方式注入 @Autowired,@Resource,@Required

2.1 在xml文件中配置依赖注入

2.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>

2.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>

2.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>

2.2 使用注解的方式注入

2.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标注的变量中。

2.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,否则将报异常。

2.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。

2.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按名称进行注入。

2.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时使用属性注入和构造方法注入了)

2.2.6 关于Autowired和@Resource

1.@Autowired注入是按照类型注入的,只要配置文件中的bean类型和需要的bean类型是一致的,这时候注入就没问题。但是如果相同类型的bean不止一个,此时注入就会出现问题,Spring容器无法启动。 
2.@Resourced标签是按照bean的名字来进行注入的,如果我们没有在使用@Resource时指定bean的名字,同时Spring容器中又没有该名字的bean,这时候@Resource就会退化为@Autowired即按照类型注入,这样就有可能违背了使用@Resource的初衷。所以建议在使用@Resource时都显示指定一下bean的名字@Resource(name="xxx") 

2.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);
            }
        };
    }
}

 

时间: 2024-12-22 15:46:10

spring中bean配置和bean注入的相关文章

总结Spring中XML配置的十二个最佳实践

Spring是一个强大的JAVA应用框架,广泛地应用于JAVA的应用程序.为PlainOldJavaObjects(POJOs)提供企业级服务.Spring利用依赖注入机制来简化工作,同时提高易测性.Springbeans及依赖,以及beans类所需的服务都在配置文件中进行了详细的说明,这个配置文件是典型的XML格式.但是它既冗长又不实用.对于需要定义大量Springbeans的大工程来说,我们难以阅读和管理它. 在这篇文章里,对于SpringXML的配置,我将向你展示12种比较好的实践.其中的

Spring中XML配置的12个技巧

Spring利用依赖注入可以获得简单而有效的测试能力.Spring beans,依赖关系,以及服务所需要的bean都将在配置文件中予以描述,配置文件一般采用XML格式.然而XML配置文件冗长而不易使用,在你进行一个使用了大量bean的大项目中它将变得难以阅读和控制. 在这篇文章中我将给你展示12种的有关Spring XML配置文件的最佳技巧.请注意另外一些因素,例如域模型的设计,会影响到XML配置,但是这篇文章更关注于XML配置的可读性和可操控性. 1.避免使用自动装配 Spring可以通过be

Spring中如何配置DataSource数据源

在Spring框架中有如下3种获得DataSource对象的方法: 1.从JNDI获得DataSource. 2.从第三方的连接池获得DataSource. 3.使用DriverManagerDataSource获得DataSource. 一.从JNDI获得DataSource SpringJNDI数据源配置信息: <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean&qu

在Spring中如何处理配置动态代理生成不同bean实现?

问题描述 最近在做一个老系统的数据库移植工作,从oracle一直到mysql,但是由于mysql数据不完整,需要先查询mysql,如果没有再去查oracle,待完整后再去掉oracle.我的想法是,抽象出dao接口,然后2套实现逻辑,最后用代理模式处理先后查询.代码如下:publicinterfaceUserDAO{publicvoidfind();}classUserDAOOracleImplimplementsUserDAO{publicvoidfind()..}classUserDAOMy

MyBatis延迟加载及在spring中集成配置

 当你要使用one to one,many to one 就会碰到N+1的问题.很明显,对象之间关联很多有A关联B,B关联C,C关联A这样的关系,如果不是采用延迟加载,很容易一下在出现成千上万对象,造成N+1的问题.   而Mybatis 设置延迟加载主要2个属性配置: <?xml version="1.0" encoding="UTF-8"?>     <!DOCTYPE configuration        PUBLIC "-

【Spring实战】—— 4 Spring中bean的init和destroy方法讲解

本篇文章主要介绍了在spring中通过配置init-method和destroy-method方法来实现Bean的初始化和销毁时附加的操作. 在java中,我们并不需要去管理内存或者变量,而在C或C++中,可以通过new和delete等方式来创建和删除变量或者对象.在Spring中,如果想要对一个bean进行初始化和结束附加一定的操作,则可以使用上述的两个方法来实现. 在介绍这两个方法前,读者需要了解Spring中bean的生命周期,最常使用的两种生命周期是:singleton和prototyp

详解Spring事务Transaction配置的五种注入方式

前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. 总结如下: Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSource.TransactionManager这两部分只是会根据数据访问方式有所变化,

spring中配置MySql数据源,怎样配置数据库信息

问题描述 我安装的Mysql5.1,进入命令模式时需要密码:自己设置的(mysql)有一个默认的数据库test,我想连接这个库,或者其他库怎么连接呢?spring中的配置如下:<bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClass

spring security 中,配置登录页面,登录页面的action一定要是j_spring_security_check吗?

问题描述 我自定义了一个登录页面,登录的action也是自己定义的,主要是去数据库验证用户名和密码是否正确.然后把当前用户存在session中.可发现Security 的http配置完后,拥有权限的用户并不能正确进入页面,都被拦截然后重定向到登录页面.因为初次使用security,有没高手给点意见,哪儿出了问题?截取配置片段:<http><form-login login-page="/demo/user/login" login-processing-url=&qu