当前位置: 首页 > news >正文

Spring 高级装配详解

一、环境与profile

​ 在3.1版本中,Spring引入了bean profile的功能。要使用profile,首先要将所有不同的bean定义整理到一个或者多个pofile之中,再将应用部署到每个环境时,确保对应的profile处于激活状态。

  • 在Java配置中,可以使用@Profile注解来指定某个bean属于哪一个profile。

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;import javax.sql.DataSource;@Configuration
    public class DevelopmentProfileConfig {@Profile("dev")@Bean()public DataSource dataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:schema.sql").addScript("classpath:test-data.sql").build();}
    }
    
  • 在XML中配置profile

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:c="http://www.springframework.org/schema/c"xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsd"profile="dev"></beans>
    

    或者

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:c="http://www.springframework.org/schema/c"xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsd"><beans profile="dev">......</beans><beans profile="prof">......</beans>
    </beans>
    

注意:

​ Spring确定那个profile处于激活状态,需要依赖两个独立的属性:

  • spring.profiles.active
  • spring.profiles.default

二、条件化的bean

@Conditional来源于spring-context包下的一个注解。Conditional中文是条件的意思,@Conditional注解它的作用是按照一定的条件进行判断,满足条件给容器注册bean。

三、处理自动装配的歧义性

1. 自动装配的歧义性

​ 例如,我们创建一个接口和三个实现该接口的类,并通过隐式的bean发现和自动装配机制进行注入bean。

// Dessert接口
public interface Dessert {void cook();
}// Cake类
@Component
public class Cake implements Dessert{private String name = "蛋糕";private String description = "水果";@Overridepublic void cook() {System.out.println(name + "加了一些" + description);}
}// Cookies类
@Component
public class Cookies implements Dessert{private String name = "饼干";private String description = "巧克力豆";@Overridepublic void cook() {System.out.println(name + "加了一些" + description);}
}// IceCream类
@Component
public class IceCream implements Dessert{private String name = "冰淇淋";private String description = "奥利奥碎屑";@Overridepublic void cook() {System.out.println(name + "加了一些" + description);}
}// 测试类
@Autowired
private Dessert dessert;@Test
public void compactDiscTest() {dessert.cook();
}

​ 此时,由于 CakeCookies IceCream 均为 Dessert,自动装配在此时会遇到歧义性,导致Spring无法做出选择,从而抛出org.springframework.beans.factory.UnsatisfiedDependencyException错误。

2. 进行处理

​ 当确实发生歧义性的时候,Spring提供了多种解决方案来解决遮掩的个问题。包括:

  • 将可选bean中的某一个设置为首选(primary)的bean;
  • 使用限定符(qualifier)来帮助Spring将可选的bean的方位缩小到只有一个bean。
1)@Primary
  1. 与@Component组合

    @Component
    @Primary
    public class Cookies implements Dessert{......
    }
    
  2. 与@Bean方法组合

    @Configuration
    public class DessertConfig {@Bean@Primarypublic Dessert dessert() {return new IceCream();}}
    
  3. <bean>元素中使用

    <bean id="iceCream"class="com.shiftycat.dessert.IceCream"primary="true">
    
2)@Qualifier

​ 在使用@Primary来表选首选bean时,如果标示了两个及以上的首选bean,那么该机制就会失效。为了解决这个问题,我们可以使用@Qualifier来规定限制条件以缩小满足要求的bean数量。

//方法1
@Component
@Qualifier
public class IceCream implements Dessert{......
}
//方法2
@Autowired
@Qualifier("iceCream")
private Dessert dessert;@Test
public void compactDiscTest() {dessert.cook();
}

当然,我们也可以创建自定义的限定符,例如:

@Component
@Qualifier("clod")
public class IceCream implements Dessert{......
}
@Autowired
@Qualifier("clod")
private Dessert dessert;@Test
public void compactDiscTest() {dessert.cook();
}

在Java配置显式定义bean的时候,@Qualifier也可以与@Bean注解一起使用。但是,此时,如果有两个bean都使用@Qualifier进行标记,也会出现错误。例如:

@Component
@Qualifier("cold")
public class IceCream implements Dessert{private String name = "冰淇淋";private String description = "奥利奥碎屑";@Overridepublic void cook() {System.out.println(name + "加了一些" + description);}
}@Component
@Qualifier("cold")
public class Popsicle implements Dessert{private String name = "棒冰";private String description = "巧克力豆";@Overridepublic void cook() {System.out.println(name + "加了一些" + description);}
}

同时,由于Java不允许在同一个条目上重复出现相同类型的多个注解,因此,使用多个@Qualifier注解编译器会提示错误。

// 编译错误
@Component
@Qualifier("cold")
@Qualifier("creamy")
public class IceCream implements Dessert{......
}

因此,我们可以使用自定义的限定符注解,从而可以更便捷地进行限定。

// 自定义限定注解
@Target({ElementType.TYPE, ElementType.CONSTRUCTOR,ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold {
}@Target({ElementType.TYPE, ElementType.CONSTRUCTOR,ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Creamy {
}@Target({ElementType.TYPE, ElementType.CONSTRUCTOR,ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Fruity {
}
@Component
@Cold
@Fruity
public class Popsicle implements Dessert{......
}@Component
@Cold
@Creamy
public class IceCream implements Dessert{......
}
@Autowired
@Cold
@Fruity
private Dessert dessert;@Test
public void compactDiscTest() {dessert.cook();
}

四、bean的作用域

​ 在默认情况下,Spring应用上下文中所有的bean都是以单例(singleton)的形式创建的。而Spring定义了多种作用域,可以基于这些作用域创建bean,包括:

  • 单例(singleton):在整个应用中,只创建bean的一个实例。
  • 原型(prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
  • 会话(Session):在Web应用中,为每个会话创建一个bean实例。
  • 请求(Request)在Web应用中,为每个请求创建一个bean实例。

bean的作用域可以使用@Scope或者<bean>元素中的scope属性进行设置。

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Cake implements Dessert{......
}
<bean id="cake"class="com.shiftycat.dessert.Cake"scope="prototype">

在Web应用中,例如有一个bean代表用户的购物车,此时它的作用域一定是会话作用域。

《Spring实战(第4版)》

http://www.lryc.cn/news/255284.html

相关文章:

  • mapbox Marker添加自定义html
  • Linux UUCP命令教程:如何在Linux系统中进行文件复制(附实例详解和注意事项)
  • 【android开发-21】android中调用系统摄像头camera拍照和相册的用法详解
  • 最新版本——Hadoop3.3.6单机版完全部署指南
  • 理解自我效能感:你的内在动力来源
  • Java第二十一章
  • Redis交互速度慢,CPU占用100%,集群方案,报错等问题
  • wpf 系统在显示器分辨率和缩放设置为非1920*1080和100%时,SelectionChanged事件响应问题分析?
  • 刷题记录--算法--简单
  • 条码生成器与Zint使用
  • C#winform上下班打卡系统Demo
  • P1 Qt的认识及环境配置
  • 单元测试Nunit的几种断言
  • 前端中的响应式布局与各个端适配
  • 2023年5个自动化EDA库推荐
  • 7-1 查找书籍
  • 【无线网络技术】——无线广域网(学习笔记)
  • 【java+vue+微信小程序项目】从零开始搭建——健身房管理平台(2)后端跨域、登录模块、springboot分层架构、IDEA修改快捷键、vue代码风格
  • NGINX相关配置
  • 如何将idea中导入的文件夹中的项目识别为maven项目
  • CleanMyMac4.16中文最新版本下载
  • 谷歌正式发布最强 AI 模型 Gemini
  • 无人机语音中继电台 U-ATC118
  • 两种测量方式的自适应卡尔曼滤波数据融合
  • .Net6支持的操作系统版本(.net8已来,你还在用.netframework4.5吗)
  • CopyOnWriteArraySet怎么用
  • uniapp得app云打包问题
  • Linux bin包生成
  • Java多人聊天
  • 自动驾驶:传感器初始标定