Spring学习--装配Bean
一 Bean装配方案
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>
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!"); } }
自动装配
通过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!"); } }
以上几种配置,程序输出结果均为以下截图
二 Spring装配中可能出现的问题
- 自动装配的歧义性:如果一个接口有多个实现类,Spring在创建Bean的时候不知道使用哪个实现类就会抛出NoUniqueBeanDefinitionException异常,此时,就需要解决装配的歧义性,解决方法是在其中一个实现类上新增@Primary注解,表明该类是首选类,如果出现歧义,则选择该实现类
以上解决方法虽然解决了歧义性的问题,但是并没有完全解决问题,因为首选类可能并不是我们真正需要的类,此时,就该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的作用域
- 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 }