• Day02 Spring和SpringBoot


    续第二章

    二、通过Java代码装配bean(配置类JavaConfig)

     应用场景:有时候自动化配置的方案行不通,因此需要明确配置Spring。比如说,想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和
    @Autowired注解的,因此就不能使用自动化装配的方案了。

    在进行显式配置的时候,有两种可选方案:Java和XML。而JavaConfig(配置代码)是更好的方案,因为它更为强大、类型安全并且对重构友好。因为它就是Java代码,就像应用程序中的其他Java代码一样。

    例:

     @Configuration注解表明这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。

    @Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终产生bean实例的逻辑。

    三、通过XML装配bean(xml文件)

    在XML配置中,意味着要创建一个XML文件,并且要以元素为根。

     元素类似于JavaConfig中的@Bean注解。

    通常来讲更好的办法是下面那种,借助id属性,为每个bean设置一个自己选择的名字:

    ---------------------------------------------------------------------------------------------------------------------------------

    借助构造器注入初始化bean

    ---------------------------------------------------------------------------------------------------------------------------------

    在XML中声明DI时,会有多种可选的配置方案和风格。具体到构造器注入,有两种基本的配置方案可供选择:

    1. 元素
    2. 使用Spring 3.0所引入的c-命名空间

    1.构造器注入bean引用:

    方法1:

     当Spring遇到这个元素时,它会创建一个CDPlayer实例。元素会告知Spring要将一个ID为compactDisc的bean引用传递到CDPlayer的构造器中。

    方法2:

     

     使用了c-命名空间来声明构造器参数。

     可以将参数名字替换为“_0”,或者“_”

     

    2.将字面量注入到构造器中:

    方法一:元素

    上面例子没有使用“ref”属性来引用其他的bean,而是使用了value属性,通过该属性表明给定的值要以字面量的形式注入到构造器之中。

    方法二:c-命名空间

     或

     装配字面量与装配引用的区别在于属性名中去掉了“-ref”后缀。

    3.装配集合

     在装配集合方面,比c-命名空间的属性更有优势。目前,使用c-命名空间的属性无法实现装配集合的功能。

    ----------------------------------------------------------------------------------------------------------------------------

    设置属性


     元素为属性的Setter方法所提供的功能与元素为构造器所提供的功能是一样的。在本例中,它引用了ID为compactDisc的bean(通过ref属性),并将其注入到compactDisc属性中(通过setCompactDisc()方法)。

    还有另一种方法代替元素:p-命名空间

     

     将字面量注入到属性中:

     与c-命名空间一样,装配bean引用与装配字面量的唯一区别在于是否带有“-ref”后缀。如果没有“-ref”后缀的话,所装配的就是字面量。

    四、自动化配置、JavaConfig以及XML配置混合匹配

    在JavaConfig中引用XML配置


    1.使用@Import注解,导入JavaConfig

    2. 使用@ImportResource注解,导入xml配置

     


    XML配置中引用JavaConfig


    在XML中,可以使用import元素来拆分XML配置。


    第3章 高级装配

    3.1 环境与profile

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

    eg:在开发环境中:

    用EmbeddedDatabaseBuilder会搭建一个嵌入式的Hypersonic数据库,它的表(schema)定义在schema.sql中,测试数据则是通过test-data.sql加载的

     在生产环境中:可能会希望使用JNDI从容器中获取一个DataSource

     

    另外,我们也可以通过元素的profile属性,在XML中配置profile bean。

     激活profile

    Spring在确定哪个profile处于激活状态时,需要依赖两个独立的属性:spring.profiles.active和
    spring.profiles.default。

    有多种方式来设置这两个属性:

    • 作为DispatcherServlet的初始化参数;
    • 作为Web应用的上下文参数;
    • 作为JNDI条目;
    • 作为环境变量;
    • 作为JVM的系统属性;
    • 在集成测试类上,使用@ActiveProfiles注解设置。

    eg:使用profile进行测试

     3.2 条件化的bean

    @Conditional注解:可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。

    eg:

     设置给@Conditional的类可以是任意实现了Condition接口的类型。可以看出来,这个接口实现起来很简单直接,只需提供matches()方法的实现即可。如果matches()方法返回true,那么就会创建带有@Conditional注解的bean。如果matches()方法返回false,将不会创建这些bean。

    3.3 处理自动装配的歧义性 

    当确实发生歧义性的时候,Spring提供了多种可选方案来解决这样的问题:

    1.将可选bean中的某一个设为首选(primary)的bean。

    2.使用限定符(qualifier)来帮助Spring将可选的bean的范围缩小到只有一个bean。

    展开:

    第一种:通过@Primary来表达最喜欢的方案。(只能用在一个身上)

     或

     或

     第二种:@Qualifier注解是使用限定符的主要方式

    例如,我们想要确保要将IceCream注入到setDessert()之中:

     所有使用@Component注解声明的类都会创建为bean,并且bean的ID为首字母变为小写的类名。因此,@Qualifier("iceCream")指向的是组件扫描时所创建的bean,并且这个bean是IceCream类的实例。

    通过声明自定义的限定符注解,我们可以同时使用多个限定符,不会再有Java编译器的限制或错误。与此同时,相对于使用原始的@Qualifier并借助String类型来指定限定符,自定义的注解也更为类型安全。

    3.4 bean的作用域

    Spring定义了多种作用域,可以基于这些作用域创建bean,包括:

    • 单例(Singleton):在整个应用中,只创建bean的一个实例。(默认作用域)
    • 原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
    • 会话(Session):在Web应用中,为每个会话创建一个bean实例。(eg:购物车)
    • 请求(Rquest):在Web应用中,为每个请求创建一个bean实例。

    如果选择其他的作用域,要使用@Scope注解,它可以与@Component或@Bean一起使用。

    eg:

    (1)使用组件扫描来发现和声明bean,设置了原型作用域

     当然也可以使用@Scope("prototype"),但是使用SCOPE_PROTOTYPE常量更加安全并且不易出错。

    (2)在Java配置中将Notepad声明为原型bean,那么可以组合使用@Scope和@Bean来指定所需的作用域:

     (3)使用XML来配置bean的话,可以使用元素的scope属性来设置作用域:


     

    proxyMode属性被设置成了ScopedProxyMode.INTERFACES,这表明这个代理要实现
    ShoppingCart接口,并将调用委托给实现bean。

     如果ShoppingCart是接口而不是类的话,这是可以的(也是最为理想的代理模式)。但如果ShoppingCart是一个具体的类的话,Spring就没有办法创建基于接口的代理了。此时,它必须使用CGLib来生成基于类的代理。所以,如果bean类型是具体类的话,我们必须要将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS,以此来表明要以生成目标类扩展的方式创建代理。

    使用XML来声明会话或请求作用域的bean,需要使用Spring aop命名空间的一个新元素:

     是与@Scope注解的proxyMode属性功能相同的Spring XML配置元素。它会告诉Spring为bean创建一个作用域代理。默认情况下,它会使用CGLib创建目标类的代理。但是我们也可以将proxy-target-class属性设置为false,进而要求它生成基于接口的代理:

    3.5 运行时值注入

    两种方式:

    • 属性占位符(Property placeholder)。
    • Spring表达式语言(SpEL)。

    3.5.1 注入外部的值

    使用@PropertySource注解和Environment

     解析属性占位符

    形式为使用“${... }”包装的属性名称

     3.5.2 使用Spring表达式语言进行装配

    SpEL(Spring Expression Language,SpEL)拥有很多特性,包括:

    • 使用bean的ID来引用bean;
    • 调用方法和访问对象的属性;
    • 对值进行算术、关系和逻辑运算;
    • 正则表达式匹配;
    • 集合操作。

    SpEL表达式要放到“#{ ... }”之中,这与属性占位符有些类似,属性占位符需要放到“${ ... }”之中

     或:

     具体语法:

    浮点值:#{3.14159}

    科学记数法:#{9.87E4}

    String类型: #{‘hello’}

    Boolean类型:#{false}

    通过ID引用其他的bean:#{sgtPeppers}

    引用sgtPeppers的artist属性:#{sgtPepper.artist}

    在表达式中使用类型:T(java.lang.Math)

     

     正则表达式:

    eg:判断一个字符串是否包含有效的邮件地址:

     SpEL还提供了查询运算符(.?[]),它会用来对集合进行过滤,得到集合的一个子集。

    eg:假设你希望得到jukebox中artist属性为Aerosmith的所有歌曲:

     SpEL还提供了另外两个查询运算符:“.^[]”和“.$[]”,它们分别用来在集合中查询第一个匹配项和最后一个匹配项

    eg:

     SpEL还提供了投影运算符(.![]),它会从集合的每个成员中选择特定的属性放到另外一个集合中

    eg:假设我们不想要歌曲对象的集合,而是所有歌曲名称的集合

  • 相关阅读:
    基于centos7安装nginx
    STL容器 —— bitset
    安卓APP webview加载H5 之间通信
    撸完这个springboot项目,我对boot轻车熟路!【源码+视频都开源】【强烈建议收藏】
    [BUG记录] vue3 setup provide/inject:无法正常进行依赖注入
    【AICFD案例教程】汽车外气动-AI加速
    Hadoop Spark太重,esProc SPL很轻
    GIRAFFE学习笔记
    C#中隐藏窗体并执行窗体逻辑的方法
    智能服装行业ERP软件帮助您提高工作效率和利润
  • 原文地址:https://blog.csdn.net/Mcdull__/article/details/126497714