zoukankan      html  css  js  c++  java
  • Spring(二) Spring装配Bean的几种方式

    Spring中,Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系。前提是我们要告诉Spring,需要创建哪些bean(bean的申明),这些bean的装配规则是什么(bean的装配)。Spring提供了3种主要的bean发现-注册-装配机制,分别为:

    • XML文件显式配置
    • Java配置类显式配置
    • 自动扫描及自动装配

    结构图如下:

    image-20200409062809460

    1. bean的申明

    XML文件显式申明

    在xml文件的<beans/>标签下的<bean>标签中申明需要Spring管理的bean。

    Java代码显示申明

    使用@Configuration标注配置类,@Bean标注bean产生的方法。

    @Configuration标注一个类为配置类。配置类的方法上标注@Bean注解,@Bean注解会告诉Spring这个方法会

    返回一个对象,改对象要注册为Spring应用上下文的Bean。该方法中包含了Bean产生的逻辑。

    配置组件自动扫描

    需要Spring管理的bean上标注@Component注解,并启用Spring的组件自动扫描。

    组件扫描启用后会扫描类上标注了@Component注解的Bean。@Component注解表明该类会作为组件类,并

    告知Spring要为这个类创建Bean。

    启用组件自动扫描的2种方式:

    • XML配置。<context:component-scan/>
    • Java配置。@ComponentScan + @Configuration

    组件扫描的命名

    默认是将类名的第一个字母变成小写作为组件的ID,也可以通过@Component注解指定ID

    2. bean的装配

    XML文件中装配

    构造器注入初始化bean:<constructor-arg>

    属性装配:<property>

    Java配置类中装配

    @Configuration标注的配置类中,@Bean注解标注的方法,会有和@Autowired标注在方法上一样的效果,会自动注入。

    自动装配

    使用@Autowired或者@Resource注解

    • 属性注入

    • 构造器注入

    • 方法注入

    3. 场景分析

    XML文件申明及装配

    申明第三方bean,并装配属性,如配置数据源:

    <!--  配置Druid数据源  -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    
        <!--  指定连接池中最大的活跃连接数  -->
        <property name="maxActive" value="20"/>
        <!--  指定启动连接池时,初始建立的连接数量  -->
        <property name="initialSize" value="1"/>
        <!--  指定连接池等待连接返回的最大等待时间,毫秒单位.  -->
        <property name="maxWait" value="60000"/>
        <!--  指定必须保持连接的最小值(For DBCP and Tomcat connection pools)  -->
        <property name="minIdle" value="1"/>
    </bean>
    

    申明第三方bean,装配自定义类,自定义类需要先在XML中申明,然后通过属性或构造器注入。如配置Shiro自定义Relam:

    <!--  注册Shiro Relam  -->
    <bean id="userRelam" class="com.lyldelove.base.shiro.UserRealm"></bean>
    
    <!--  配置Shiro SecurityManager  -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userRelam"/>
    </bean>
    

    UserRealm.java不需要标注任何注解

    Java配置类配置

    使用@Configuration标注类为配置类,使用@Bean申明对象,@Bean标注的方法在一个配置类中,是会自动注入的,同样是配置Shiro自定义Relam:

    @Configuration
    public class ShiroConfig
    {
        /**
         * 自定义Realm
         */
        @Bean
        public UserRealm userRealm()
        {
            UserRealm userRealm = new UserRealm();
            return userRealm;
        }
    
        /**
         * 安全管理器
         */
        //标注@Bean,会自动注入上面定义的UserRealm
        @Bean
        public SecurityManager securityManager(UserRealm userRealm)
        {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 设置realm.
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    }
    

    UserRealm.java不需要标注任何注解

    组件扫描和自动装配

    一般使用组件扫描的,都是不需要再配置的,如@Controller、@Service等,直接使用就可以的。这种类型只需要在类上标注@Component,在使用的地方@Autowired引入即可。

    4. 小思考

    • 可以简单这么理解:@Configuration注解相当于一个xml配置文件,相当于一个<beans>@Bean注解相当于<bean/>

    • XML配置中,<bean/>调用的是申明对象的默认/指定构造器来创建Bean的,而Java配置类中,@Bean标注的方法可以自定义写对象生成的逻辑,更加灵活。当然我们可以编写Java类,在类中写bean的逻辑,不使用@Configuration申明而是直接通过XML的方式进行申明,都是可以的。有的时候,使用配置类申明对象会简单很多,比如:申明多线程ScheduledExecutorService

      Java配置类申明:

      @Configuration
      public class ThreadPoolConfig
      {
          // 核心线程池大小
          private int corePoolSize = 50;
      
          /**
           * 执行周期性或定时任务
           */
          @Bean(name = "scheduledExecutorService")
          protected ScheduledExecutorService scheduledExecutorService()
          {
              return new ScheduledThreadPoolExecutor(corePoolSize,
                      new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
              {
                  @Override
                  protected void afterExecute(Runnable r, Throwable t)
                  {
                      super.afterExecute(r, t);
                      Threads.printException(r, t);
                  }
              };
          }
      }
      

      这种情况,使用XML进行申明就会很麻烦:

      • 需要申明ScheduledThreadPoolExecutor
      • 需要申明BasicThreadFactory
      • 需要申明Builder
      • 然后将上面3个组件组装起来
    • 个人建议:如果项目使用的是XML文件管理bean,就尽量都用XML申明;用@Configuration管理的,就尽量都用@Configuration,且配置类放到一起。当然Java配置类是趋势,且更好管理。

  • 相关阅读:
    Oracle 临时事务表 全局临时表_global temporary table
    js String Trim函数
    解决Navicat Error: Missing required libmysql_d.dll
    win8双屏敲代码
    条件注释判断浏览器
    Eclipse 中Alt+/快捷键失效的解决办法。
    解决java写入xml报错org.w3c.dom.DOMException:DOM002 Illeg
    用解释计划评估创建索引后对单表查询效率的影响
    在某文件夹查找以日期命名的目录,如果早已目标时间则删除之
    (Python)正则表达式进行匹配
  • 原文地址:https://www.cnblogs.com/lyldelove/p/12670982.html
Copyright © 2011-2022 走看看