Spring学习--装配Bean

Spring Bean装配详解
本文深入讲解Spring框架中Bean的装配方式,包括XML显式配置、Java注解配置及自动装配,探讨装配过程中可能出现的问题及解决方案,并介绍Bean作用域的设定。

Spring学习--装配Bean

一 Bean装配方案

  1. XML显式配置
    通过XML文件配置Bean的创建和依赖,需要新增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:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd"> 
    
        <bean id="logService" class="com.qyj.service.LogService"></bean>
    
        <bean id="userService" class="com.qyj.service.UserService">
            <constructor-arg name="logService" ref="logService"></constructor-arg>
        </bean>
    </beans>
  2. Java中显式配置
    通过Java注解(@Configuration)装配Bean,定义新的配置类,并新增@Configuration()注解

    //    新增配置类
    package com.qyj.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration; 
    import com.qyj.service.IUserService;
    import com.qyj.service.LogService;
    import com.qyj.service.UserService;
    
    @Configuration
    @ComponentScan(basePackageClasses = { LogService.class })//注明要加载的Bean所在包
    public class springConfig {
    
        @Bean
        public LogService logService() {
            return new LogService(); 
        }
    
        @Bean
        public IUserService userService() {
            return new UserService(logService()); 
        }
    }
    
    //修改main方法
    public class App {
        public static void main(String[] args) { 
            ApplicationContext context = new AnnotationConfigApplicationContext(springConfig.class);
            IUserService userService = context.getBean(IUserService.class);
            userService.DoWork();
            System.out.println("Hello World!");
        }
    } 
    
  3. 自动装配
    通过Spring注解的方式装配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"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
        <!--启用扫描并设置Bean扫描的根包名称 -->
        <context:component-scan base-package="com.qyj" />
    </beans>
    

    代码

    //IlogService接口
    package com.qyj.service; 
    public interface IlogService {
        public void Info(String message);
    }
    //IUserService接口
    package com.qyj.service; 
    public interface IUserService {
    
        public void DoWork();
    }
    
    //IlogService实现类 
    package com.qyj.service; 
    import org.springframework.stereotype.Component; 
    @Component
    public class LogService implements IlogService {
    
        public void Info(String message) {
            System.out.println("LogService Info Method DoWork,Info:" + message);
        }
    
    }
    
    //IUserService实现类 并需要构造注入IlogService实现类
    package com.qyj.service; 
    import org.springframework.beans.factory.annotation.Autowired; 
    @Component
    public class UserService implements IUserService {
    
        private IlogService logService; 
        // 构造函数注入
        @Autowired
        public UserService(IlogService logService) {
            this.logService = logService;
        }
    
        public void DoWork() {
            this.logService.Info("this is UserSerivice DoWork Method Invoke ");
        } 
    }
    
    //main方法
    package com.qyj.service; 
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext; 
    import com.qyj.service.IUserService;
    
    public class App {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 
            IUserService userService = context.getBean(IUserService.class); 
            userService.DoWork(); 
            System.out.println("Hello World!");
        }
    }
    

    以上几种配置,程序输出结果均为以下截图
    284679-20180914153946334-466988524.png

二 Spring装配中可能出现的问题

  1. 自动装配的歧义性:如果一个接口有多个实现类,Spring在创建Bean的时候不知道使用哪个实现类就会抛出NoUniqueBeanDefinitionException异常,此时,就需要解决装配的歧义性,解决方法是在其中一个实现类上新增@Primary注解,表明该类是首选类,如果出现歧义,则选择该实现类
  2. 以上解决方法虽然解决了歧义性的问题,但是并没有完全解决问题,因为首选类可能并不是我们真正需要的类,此时,就该Spring的限定符出手了,通过限定符,你可以明确的告知依赖方注入那个类,通常使用@Qualifier注解实现。它可以与@Autowired和@Inject协同使用,在注入的时候指定想要注入进去的是哪个bean
    eg:

        @AutoWare
        @Qualifier("studentService") //参数内容为Bean的id,但是此时限定符是固定的,是紧耦合的
        public void setUserService(IUserService userService)
        { 
          // do something 
        }  
        //针对以上问题,使用Spring的自定义限定符解决  
        //被注入类型
        @Comonent
        @Qualifier("student") 
        @Qualifier("smallstudent")
        public class StudentService implements  IUserService
        {
            // do something
        } 
        //需要注入的地方
        @AutoWare
        //此时参数内容为要注入的类的自定义限定符,无论是否修改StudentService的名称
        //主要不修改StudentService的限定符名称,该类将正确注入
        @Qualifier("student")
        //新加此限定的主要原因是如果两个限定符号student,则可通过smallstudent再次限定
        @Qualifier("smallstudent") 
        //通过以上两个限定,则此处会正确的注入StudentService对象
        public void setUserService(IUserService userService)
        { 
         // do something 
        }

三 Bean的作用域

  1. Bean的作用域有以下几种:
    • 单利(Singleton):在整个应用中,只创建一个实例,是spring默认的形式
    • 原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的实例
    • 会话(Session):在Web应用中,为每个会话创建一个实例
    • 请求(Request):在Web应用中,为每个请求创建一个实例
      因为Spring默认的作用域是Singleton的,所以如果需要设置类的作用域.可通过@Scope注解实现
         @Comonent
         //以下两种选一种即可 比较 建议第二种
         @Scope("prototype") 
         @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
         public class StudentService implements  IUserService
         {
             // do something
         }

转载于:https://www.cnblogs.com/ShuiMu/articles/9646985.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值