spring使用之旅 ---- bean的装配

Spring Bean 配置详解
本文详细介绍了Spring框架中Bean的多种配置方式,包括组件扫描、手动装配Bean、条件配置等,并探讨了Bean的作用域及解决注入歧义的方法。
     基础配置
    • 启用组件扫描配置
                    Java类配置文件方式
package com.springapp.mvc.application ;

import  org.springframework.context.annotation.ComponentScan ;
import  org.springframework.context.annotation.Configuration ;

/**
 * Created by xuc on 2018/1/7.
 * 配置类
 */
@ComponentScan(basePackages = {"com.springapp.mvc"})
@Configuration
public class Application {
}
 注:此处@Configuration为声明该类为配置文件类,@ComponentScan为声明开启扫描功能,若未配置基础包属性,则默认扫描该配置类所在当前包,否则扫描基础包定义的包

xml文件配置
<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 http://www.springframework.org/schema/context/spring-context.xsd" >
    < context:component-scan base-package="com.springapp.mvc" />
    <bean  class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property  name ="prefix"  value ="/WEB-INF/pages/" />
        <property  name ="suffix"  value =".jsp" />
    </bean>
</beans>
    •  手动装配bean
          在大部分情况下我们都是使用组件扫描的的方式来装载bean,但有时候在使用第三方框架时,需要指定某些配置类,这种情况下通过手动配置则更加合适
                    Java类装配方式
package com.springapp.mvc.application ;

import com.springapp.mvc.easyBean.Braves ;
import com.springapp.mvc.easyBean.Sword ;
import  org.springframework.context.annotation.Bean ;
import  org.springframework.context.annotation.ComponentScan ;
import  org.springframework.context.annotation.Configuration ;

/**
 * Created by xuc on 2018/1/7.
 * 配置类
 */
@ComponentScan( basePackages = { "com.springapp.mvc"})
@Configuration
public class Application {
    @Bean(name = "braves")
      public Braves  braves() {
          return new Braves(sword()) ;
    }
      @Bean
     public Braves  braves1() {
        Braves braves =  new Braves() ;
        braves.setSword(sword()) ;
        return braves ;
    }
      @Bean
     public Sword  sword() {
          return new Sword() ;
    }
}
             注:此处首先声明配置文件类,再通过在方法上@Bean注解,则spring将知道该方法会返回一个bean且注册到spring上下文中。@Bean注解若配置name属性,则Bean的ID为该值,否则默认和方法名一样。braves( ) 和braves1( ) 方法分别实现了构造函数注入和set方式注入
                    xml文件配置方式
<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 http://www.springframework.org/schema/context/spring-context.xsd" >

    < context :component-scan  base-package ="com.springapp.mvc" />

    <bean class="com.springapp.mvc.easyBean.Sword" id="sword"></bean>
    <bean class="com.springapp.mvc.easyBean.Braves" id="braves">
        <constructor-arg ref="sword"></constructor-arg>
    </bean>
    <bean class="com.springapp.mvc.easyBean.Braves" id="braves1">
        <property name="sword" ref="sword"></property>
    </bean>

    <bean  class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property  name ="prefix"  value ="/WEB-INF/pages/" />
        <property  name ="suffix"  value =".jsp" />
    </bean>
</beans>
               braves bean 和 braves1 bean分别实现了构造函数注入和set方式注入.
    • Java类和xml文件混合配置(单或多)
                   Java类配置
package com.springapp.mvc.application ;

import com.springapp.mvc.easyBean.Sword ;
import org.springframework.context.annotation.* ;

/**
 * Created by xuc on 2018/1/7.
 * 配置类
 */
@ComponentScan( basePackages = { "com.springapp.mvc"})
@Configuration
@Import(Application1.class)
@ImportResource("classpath:mvc-dispatcher-servlet.xml")
public class Application {
      @Bean
     public Sword  sword() {
          return new Sword() ;
    }
}
注:此处@Import 注解为导入配置java类,@ImportResource注解为导入配置xml文件,此处可配置多个,通过都好隔开
                  xml文件配置
<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 http://www.springframework.org/schema/context/spring-context.xsd" >

    < context :component-scan  base-package ="com.springapp.mvc" />

    <import resource="mvc-dispatcher-servlet1.xml"></import>
    <bean class="com.springapp.mvc.application.Application"
></bean>

    <bean  class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property  name ="prefix"  value ="/WEB-INF/pages/" />
        <property  name ="suffix"  value =".jsp" />
    </bean>
</beans>

     条件配置
    •  spring profile 实现跨环境配置
                      1.配置profile bean
               java类配置
package com.springapp.mvc.application ;

import ...

/**
 * Created by xuc on 2018/1/7.
 * 配置类
 */
@ComponentScan( basePackages = { "com.springapp.mvc"})
@Configuration
public class Application {
      @Bean
     public Braves  braves(IArms arms){
          return new Braves(arms) ;
    }
      @Bean
    @Profile ("dev")
      public Sword  sword() {
          return new Sword() ;
    }
      @Bean
    @Profile ("test")
      public Machete  machete(){
          return new Machete() ;
    }
}
              注:通过@Profile注解声明该bean属于哪种环境下的(常见于数据库连接操作)
               xml文件配置
<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 http://www.springframework.org/schema/context/spring-context.xsd" >

    < context :component-scan  base-package ="com.springapp.mvc" />

    <beans profile="dev">
        <bean class="com.springapp.mvc.easyBean.Sword"></bean>
    </beans>
    <beans profile="test">
        <bean class="com.springapp.mvc.easyBean.Machete"></bean>
    </beans>

    <beans>
        <bean  class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >
            <property  name ="prefix"  value ="/WEB-INF/pages/" />
            <property  name ="suffix"  value =".jsp" />
        </bean>
    </beans>
</beans>
                    2.激活spring profile
<web-app  version ="2.4"
    xmlns ="http://java.sun.com/xml/ns/j2ee"  xmlns: xsi ="http://www.w3.org/2001/XMLSchema-instance"
    xsi :schemaLocation ="http://java.sun.com/xml/ns/j2ee 
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >

   <display-name>Spring MVC Application </display-name>

   <context-param>
      <param-name>spring.profiles.default</param-name>
      <param-value>dev</param-value>
   </context-param>
    <servlet>
      <servlet-name>mvc-dispatcher </servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class>
      <init-param>
         <param-name>spring.profiles.default</param-name>
         <param-value>dev</param-value>
      </init-param>
        <load-on-startup>1 </load-on-startup>
   </servlet>

   <servlet-mapping>
      <servlet-name>mvc-dispatcher </servlet-name>
      <url-pattern>/ </url-pattern>
   </servlet-mapping>
</web-app>
               注:在web应用中,只需配置spring.profiles.default 或 spring.profiles.active,前者为默认后者为激活
                    3.测试一下
               在配置“dev”的情况下,只会有sword bean存在,使用machete bean则会报类不存在异常!
    • condition实现条件注册bean
                    定义一个实现condition接口的类,实现matches( )方法,在方法里面做校验判断
package com.springapp.mvc.application ;

import org.springframework.context.annotation.Condition ;
import org.springframework.context.annotation.ConditionContext ;
import org.springframework.core.env.Environment ;
import org.springframework.core.type.AnnotatedTypeMetadata ;

/**
 * Created by xuc on 2018/1/7.
 * 条件判断bean是否创建
 */
public class AppCondition  implements Condition {
      @Override
     public boolean  matches(ConditionContext conditionContext AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment() ;
        if (environment.acceptsProfiles( "dev") || environment.acceptsProfiles( "test")){
              return true;
        }
          return false;
    }
}
                    注:@profile注解value校验就是通过condition实现的,ProfileCondition为其实现类如下:

@Retention(RetentionPolicy. RUNTIME)
@Target({ElementType. TYPE ElementType. METHOD})
@Documented
@Conditional(ProfileCondition.class)
public @ interface  Profile {

    /**
    * The set of profiles for which the annotated component should be registered.
    */
   String[]  value() ;

}

class ProfileCondition  implements Condition {

    @Override
    public boolean  matches(ConditionContext context AnnotatedTypeMetadata metadata) {
        if (context.getEnvironment() !=  null) {
         MultiValueMap<String Object> attrs = metadata.getAllAnnotationAttributes( Profile. class.getName()) ;
         if (attrs !=  null) {
              for (Object value : attrs.get( "value")) {
                if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
                    return true;
               }
            }
              return false;
         }
      }
        return true;
   }

}
    • bean注入歧义性问题
                    1.在待注入bean上加@Primary注解,声明该bean为优先注入
package com.springapp.mvc.application ;

import com.springapp.mvc.easyBean.Braves ;
import com.springapp.mvc.easyBean.IArms ;
import com.springapp.mvc.easyBean.Machete ;
import com.springapp.mvc.easyBean.Sword ;
import org.springframework.context.annotation.* ;

/**
 * Created by xuc on 2018/1/7.
 * 配置类
 */
@ComponentScan( basePackages = { "com.springapp.mvc"})
@Configuration
public class Application {
      @Bean
    @Conditional(AppCondition. class)
      public Braves  braves(IArms arms){
          return new Braves(arms) ;
    }
      @Bean
    @Profile( "dev")
     @Primary
     public Sword  sword() {
          return new Sword() ;
    }
      @Bean
    @Profile( "test")
      public Machete  machete(){
          return new Machete() ;
    }
}
                   
                    2.在被注入bean上加@Qualifier注解
package com.springapp.mvc.application ;

import com.springapp.mvc.easyBean.Braves ;
import com.springapp.mvc.easyBean.IArms ;
import com.springapp.mvc.easyBean.Machete ;
import com.springapp.mvc.easyBean.Sword ;
import  org.springframework.beans.factory.annotation.Qualifier ;
import org.springframework.context.annotation.* ;

/**
 * Created by xuc on 2018/1/7.
 * 配置类
 */
@ComponentScan( basePackages = { "com.springapp.mvc"})
@Configuration
public class Application {
      @Bean
    @Qualifier( "sword")
      public Braves  braves(IArms arms){
          return new Braves(arms) ;
    }
      @Bean
    @Profile( "dev")
      public Sword  sword() {
          return new Sword() ;
    }
      @Bean
    @Profile( "test")
      public Machete  machete(){
          return new Machete() ;
    }
}
                    注:此处若存在多个(即多优先级),可自定义注解
    • bean的作用域
作用域 描述
singleton 该作用域将 bean 的定义的限制在每一个 Spring IoC 容器中的一个单一实例(默认)。
prototype 该作用域将单一 bean 的定义限制在任意数量的对象实例。
request 该作用域将 bean 的定义限制为 HTTP 请求。只在 web-aware Spring ApplicationContext 的上下文中有效。
session 该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效。
global-session 该作用域将 bean 的定义限制为全局 HTTP 会话。只在 web-aware Spring ApplicationContext 的上下文中有效。
package com.springapp.mvc.application ;

import com.springapp.mvc.easyBean.Braves ;
import com.springapp.mvc.easyBean.IArms ;
import com.springapp.mvc.easyBean.Machete ;
import com.springapp.mvc.easyBean.Sword ;
import  org.springframework.beans.factory.annotation.Qualifier ;
import org.springframework.context.annotation.* ;
import org.springframework.web.context.WebApplicationContext ;

/**
 * Created by xuc on 2018/1/7.
 * 配置类
 */
@ComponentScan( basePackages = { "com.springapp.mvc"})
@Configuration
public class Application {
      @Bean
     public Braves  braves(IArms arms){
          return new Braves(arms) ;
    }
      @Bean
    @Profile( "dev")
      @Scope( value = WebApplicationContext. SCOPE_GLOBAL_SESSION ,
             proxyMode = ScopedProxyMode. TARGET_CLASS)
      public Sword  sword() {
          return new Sword() ;
    }
      @Bean
    @Profile( "test")
      public Machete  machete(){
          return new Machete() ;
    }
}
               注:此处通过@Scope注解重新定义sword bean为会话级作用域,由于在使用braves时会优先加载sword,通过proxyMode声明代理该类,
          即通过延迟注入的形式实现session级的sword注入到单例级的braves。如果该是接口的话:“proxyMode = ScopedProxyMode.INTERFACES”

               未完,待续....

环境: IDEA、Spring4.0
参考资料: 《spring实战》










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值