spring(2)装配Bean
- m1)在XML中进行显式配置;
- m2)在java中进行显式配置;
- m3)隐式的bean 发现机制和自动装配;
- A1)Spring的配置风格是可以互相搭配的,所以你可以选择使用XML 装配一些bean,使用Spring基于java 的配置(JavaConfig)来装配另一些bean,而剩下的bena可以让Spring自动发现;
- A2)而原书作者建议:尽可能地使用自动配置的机制;而必须要显示配置bean的时候,原书作者推荐类型安全并且比XML 更加强大的 JavaConfig;
- A3)最后,只有当你想要使用便利的xml 命名空间,并且在 JavaConfig 中没有同样的实现时,才应该使用 XML;
1.1)组件扫描:Spring会自动发现应用上下文中所创建的bean;1.2)自动装配:Spring自动满足bena之间的依赖;
A1)component注解表明:该类会作为组件类,并告知spring要为这个类创建bean.(干货——@Component注解的作用)A2)组件扫描默认是不启用的。我们需要显式配置一下spring, 从而命令它去寻找带有@Component注解的类,并为其创建bean;
package com.spring.chapter2;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan
public class CDPlayerConfig {
}
A1)类CDPlayerConfig 通过 java 代码定义了Spring的装配规则;A2)类CDPlayerConfig 并没有显式地声明任何bean, 只不过它使用了 @ComponentScan 注解,这个注解能够在Spring中启用组件扫描;(干货——@ComponentScan注解的作用)A3)@ComponentScan注解:默认会扫描配置类相同的包。因为CDPlayerConfig 位于 com.spring.chapter2,那所以Spring将会扫描这个包及其所有子包,查找带有 @Component注解的类;
<context:component-scan base-package="com.spring.chapter2">
A1)该测试用例使用了 Spring 的 SpringJUnit4ClassRunner:以便在测试开始的时候自动创建 Spring的应用上下文;A2)注解@ContextConfiguration:会告诉它需要在 CDPlayerConfig中加载配置;因为CDPlayerConfig 类中包含了@ComponentScan, 所以最终的应用上下文应该包含JayChou bean;(干货——@ContextConfiguration注解的作用)
@Component("jay chou")
public class JayChou implements Disc{
@Named("jay chou")
public class JayChou implements Disc{
@Configuration
@ComponentScan("com.spring.chapter1")
public class CDPlayerConfig { }
1.2.1)如果想更加清晰地表明想要设置的基础包,通过basePackage属性进行配置:@Configuration @ComponentScan(basePackage="com.spring.chapter1") public class CDPlayerConfig { }
1.2.2)当然也可以设置多个基础包@Configuration @ComponentScan(basePackage={"com.spring.chapter1", "com.spring.chapter2"}) public class CDPlayerConfig { }
2.1)problem:在上面的荔枝中,所设置的 基础包是String类型的;这种方法是类型不安全的2.2)solution:@ComponentScan注解还提供了另外一种方法,那就是将其指定为包中所包含的类或接口:@Configuration @ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class}) public class CDPlayerConfig { }
public class CDPlayer implements MediaPlayer{private Disc disc;@Autowiredpublic CDPlayer(Disc disc) {this.disc = disc;}public void play() {disc.play();}
}
A0)上述第4行代码的 @Autowired:该注解表明 当Spring创建CDPlayer bean 的时候,会通过这个构造器来进行实例化并且会传入一个可设置给 Disc 类型的bean;
A1)注解@Autowired 不仅能够用在构造器上,还能用在属性的setter方法上;@Autowiredpublic void setDisc(Disc disc) {this.disc = disc;}
A2)实际上, 注解 @Autowired 可以用在类的任何方法上;
4.1)为了避免抛出异常,可以将required设置为 false:将required 属性设置为false时,Spring 会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean 处于未装配的状态;@Autowired(required=false)public CDPlayer(Disc disc) {this.disc = disc;}
4.2)如果有多个bean满足依赖关系的话,Spring将会抛出异常,表明没有明确指定要选择哪个bean 进行自动装配;
@Beanpublic Disc jaychou() {return new JayChou();}
对以上代码的分析(Analysis):@Bean注解会告诉Spring 这个方法将会返回一个对象,该对象要注册为 Spring应用上下文中的bean;方法体中包含了最终产生bean实例的逻辑;(干货——@Bean注解的作用)
2.1)可以自定义bean的ID:@Bean(name="our jaychou")public Disc jaychou() {return new JayChou();}
1.1)problem:前面声明的 JayChou(Disc)自身没有其他依赖;现在要声明CDPlayer bean,它依赖与 JayChou,那么在 JavaConfig中,要如何将它们装配在一起呢?1.2)solution:在 JavaConfig中装配bean的最简单方式就是引用创建bean的方法。如下面就是一种声明 CDPlayer的可行方法:// defined in CDPlayer. @Bean(name="our jaychou")public Disc jaychou() {return new JayChou();} @Beanpublic CDPlayer cdPlayer() {return new CDPlayer(jaychou());}
对以上代码的分析(Analysis):
A1)cdPlayer()方法与jaychou()方法有些区别:在这里并没有使用默认的构造器构建实例,而是调用了需要传入 Disc 对象 的构造器来创建CDPlayer实例;A2)看起来 Disc 是通过 jaychou()方法得到的,但case并非总是如此:因为jaychou()方法上添加了 @Bean注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行调用;(干货中的干货——也即是对jaychou方法的多次调用都只会返回同一个bean,而不是多个bean);
看个荔枝) cdPlayer方法返回的CDPlayer的Disc 对象 与 anotherPlayer方法返回的CDPlayer的Disc 对象是同一个; (干货——在软件领域中,多个播放器player可以使用同一张唱片jaychou)
@Beanpublic CDPlayer cdPlayer() {return new CDPlayer(jaychou());}@Beanpublic CDPlayer anotherPlayer() {return new CDPlayer(jaychou());}
对以上代码的分析(Analysis):
A1)默认情况下,Spring中的bean 都是单例的,我们并没有必要为第2个CDPlayer bena创建相同的 JayChou 唱片;A2)总之一句话: Spring会拦截对 jaychou()方法的调用并确保返回的是 Spring所创建的bean,也就是Spring本身首次调用jaychou()方法所创建的bean;
Attention)
A1)需要提醒的是,我们在这里使用CDPlayer的构造器实现了 DI 功能,但是我们完全可以采用其他风格的DI 配置;比如,如果想通过Setter 方法注入Disc的话,代码像这个样子:@Beanpublic CDPlayer cdPlayer(Disc disc) {CDPlayer cdPlayer = new CDPlayer(disc);cdPlayer.setDisc(disc);return cdPlayer;}
A2)带有@Bean 注解的方法可以采用任何必要的java 功能来产生bean实例。构造器和Setter 方法只是 @Bean方法的两个简单样例;
2)对@bean注解的另外一种理解方式
@Bean
public CDPlayer cdPlayer(Disc disc) {return new CDPlayer(disc);
}
对以上代码的分析(Analysis):当Spring 调用cdPlayer()创建CDPlayer bean的时候,它会自动装配一个Disc 到配置方法中。通过这种方式引用其他的bean 通常是 最佳的选择,因为它不会要求将 Disc 声明到同一个配置类中,在这里甚至没有要求 Disc 必须要在 JavaConfig中声明,实际上它可以通过组件扫描功能自动发现或通过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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context">
<!-- configuration details go here -->
</beans>
<bean class="com.spring.chapter1.JayChou" />
A1)默认的bean id :根据全限定类名来进行命名,在本例中default id == com.spring.chapter1.JayChou#0,#0是一个计数的形式,用来区分相同类型的其他bean;A2)自定义bean id:<bean id="mydiy" class="com.spring.chapter1.JayChou" />
A1)减少繁琐: 为了减少xml 中繁琐的配置,只对那些需要按名字引用的bean 进行明确的命名;(比如你需要将对它引用注入到另一个bean中);(干货——引入减少繁琐)A2)当Spring发现这个 <bean>元素时,它将会调用 其默认构造器来创建bean;在XML配置中,bean的创建更加被动;A3)在这个简单的<bean>声明中,我们把bean的类型以字符串的形式设置在了 class属性中,谁知道它是对的还是不对的。。为了检查该字符串是否是实际的类型,借助Spring Tool Suit检查XML的合法性;(感觉这个原书作者在打ad 一样,hh);
s1)<constructor-arg>元素;s2)使用spring3.0 所引入的 c-命名空间;
scheme1)通过XML配置 来实现 “CDPlayer 类需要依赖(引用) Disc的实现类” 的需求;
<bean id="cdPlayer" class="com.spring.chapter2.CDPlayer"><constructor-arg ref="jaychou" /> </bean> <bean id="jaychou" class="com.spring.chapter2.JayChou"> </bean>
scheme2)通过c-命名空间 来实现 “CDPlayer 类需要依赖(引用) Disc的实现类” 的需求;
step1)要使用spring 的c-命名空间的话,必须要在XML 的顶部声明其模式,如下所示:<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> ... </beans>
step2)使用c-命名空间来声明构造器参数:<bean id="cdPlayer" class="com.spring.chapter2.CDPlayer" c:cd-ref="jaychou" />
<bean id="cdPlayer" class="com.spring.chapter2.CDPlayer"
c:_0-ref="jaychou" />
3.1)通过XML来装配<bean id="leehom" class="com.spring.chapter2.Leehom"><constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" /><constructor-arg value="The Beatles" /> </bean>
3.2)通过c-命名空间来装配
<bean id="leehom"class="com.spring.chapter2.Leehom"c:_title="Sgt. Pepper's Lonely Hearts Club Band"c:_artist="The Beatles" />
s1)最简单的方法是将列表设置为null:
s2)更好的解决方法是提供给一个磁道名称的列表:使用 <list>元素将其声明为一个列表:
s3)当然了,我们也可以使用<ref>元素替代 <value>,实现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:aop="http://www.springframework.org/schema/aop"xmlns:c="http://www.springframework.org/schema/c"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="leehom" class="com.spring.chapter2.Leehom"c:_0="十八般武艺" c:_1="Leehom Wang"><constructor-arg><list><value>Sgt. Pepper's Lonely Hearts Club Band</value><value>With a Little Help from My Friends</value><value>Lucy in the Sky with Diamonds</value><value>Getting Better</value><value>Fixing a Hole</value><!-- ...other tracks omitted for brevity... --></list></constructor-arg></bean>
</beans>
public class Leehom implements Disc {private String title;private String artist;private List<String> tracks;public Leehom() {}public Leehom(String title, String artist, List<String> tracks) {this.title = title;this.artist = artist;this.tracks = tracks;}public void setTitle(String title) {this.title = title;}public void setArtist(String artist) {this.artist = artist;}public void setTracks(List<String> tracks) {this.tracks = tracks;}public void play() {System.out.println("Playing " + title + " by " + artist);for (String string : tracks) {System.out.println("-track: " + string);}}@Overridepublic String getName() {return artist;}
}
2.1)为了启用p-命名空间,必须要在 XML 文件中与其他的命名空间一起对其进行声明;2.2)利用p-命名空间,按照以下方式装配disc属性;
3)将字面量注入到属性中
3.1)新的Leehom 类如下所示:
3.2)通过<property>元素的value属性注入3.3)通过spring的p-命名空间来实现注入
A1)与c-命名空间一样,装配bean 引用与装配字面量的唯一区别是: 是否带有“-ref”后缀,如果没有该后缀的话,所装配的就是字面量(如String类型);(干货——装配bean 引用与装配字面量的唯一区别是: 是否带有“-ref”后缀,如果没有该后缀的话,所装配的就是字面量)A2)不能通过p-命名空间来装配集合;但可以使用 Spring util-命名空间中的一些功能来简化 Leehom bean;
step1)需要在XML 中声明util-命名空间及其模式
step2)util-命名空间所提供的功能之一是 <util:list>元素,它会创建一个 列表的bean;step3)通过<util:list>元素创建了List bean,现在,我们将磁道列表 bean(tracklist) 注入到 Leehom 的tracks 属性中;
spring(2)装配Bean相关推荐
- Spring之装配Bean(一)
Spring中装配bean的三种主要方式 1.隐式的bean发现机制和自动化装配 组件扫描( component scanning) : Spring会自动发现应用上下文中所创建的bean. 自动装配 ...
- spring三: 装配bean( 在xml中进行显式配置, 在java中进行显式配置)
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class); SpringCon ...
- spring二:装配bean(自动装配)
创建应用对象之间协作关系的行为通常称为装配(wiring),这就是依赖注入(DI)的本质. Spring提供了三种主要的装配机制: 1. 在xml中进行显式配置. 2. 在java中进行显式配置. ...
- Spring实战(三)Spring中装配Bean的三种方式---XML、JavaConfig、AutoWire
创建应用对象之间协作关系的行为称为装配(wiring),这也是依赖注入的本质. Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,而开发者需要告诉Spring需要创建哪些 ...
- Spring自动装配Bean
除了使用 XML 和 Annotation 的方式装配 Bean 以外,还有一种常用的装配方式--自动装配.自动装配就是指 Spring 容器可以自动装配(autowire)相互协作的 Bean 之间 ...
- Spring基础—装配bean(一)
在讲解Spring配置beans之前首先想一下一部成功的电影都需要哪些成员参与.首先,最重要的是要有导演.编剧.演员和投资人:其次,还有没那么明显的成员,音乐人.特技演员和艺术指导:此外,还有其他很重 ...
- Spring笔记——装配Bean
1.Spring配置的可选方案 在XML中进行显式配置. Java中进行显式配置. 隐式的bean发现机制和自动装配. 2.自动化装配bean Spring从两个角度来实现自动化装配: 组件扫描(co ...
- Spring 自动化装配Bean
声明一张cd的接口: public interface CompactDisc {public abstract void play(); } 实现cd接口: @Component("Sgt ...
- spring自动装配Bean的五种方式
no:默认方式,手动装配方式,需要通过ref设定bean的依赖关系 byName:根据bean的名字进行装配,当一个bean的名称和其他bean的属性一致,则自动装配 byType:根据bean的类型 ...
最新文章
- Web项目使用nginx实现代理端口访问,看这篇就够了
- 微信小程序的wxss好难啊,记录我的搞笑界面
- 点云网络的论文理解(七)-Frustum PointNets for 3D Object Detection from RGB-D Data
- 【Cocosd2d实例教程七】Cocos2d实现超炫的粒子效果!!
- pythn3随笔-enumerate()
- JVM 参数使用总结
- 华科10年计算机考研复试笔试(算法基础)(1)
- ffmpeg源码分析:transcode()函数
- 只有我能做的工作,权限关了?
- [转] 各船公司认识
- 百度地图Android开发清除上一次驾车导航路线
- http://coffeejp.com/bbs/forum.php?mod=viewthread,问题列表_华泰证券网络路演_新浪网
- Filtered off site request to
- 村医计算机在线考试答案,资讯详情-村医去卫生院换电脑,却被“威胁”停业整顿?-医德帮诊所生态服务平台-为基层诊所赋能...
- 书单 | 带你轻松度假的10本好书!
- 软件质量之道:PCLint之中的一个
- android浏览器 url,java – 在Android浏览器中获取当前URL
- mysql5.6.37 主从同步_Mysql5.6.x版本半同步主从复制的开启方法
- 北上深杭广漂,似曾相识的代码人生
- 计算智能课程设计(遗传算法求解无约束单目标优化问题)
热门文章
- Codeforces Round #715 (Div. 1) C. Complete the MST 补图 + 思维 + 最小生成树
- 【CF 1188 A1,B,C】Add on a Tree // Count Pairs // Array Beauty
- CF25E-Test【AC自动机,bfs】
- AT4502-[AGC029C]Lexicographic constraints【二分,栈】
- POJ1958-Strange Towers of Hanoi【递推】
- ssl初一组周六模拟赛【2018.3.24】
- SSL-练习题目:种树 题解
- codeforces1484 B. Restore Modulo(数学)
- codeforces1438 E.Yurii Can Do Everything
- 【快速幂】小明解密码 (jzoj 2146)