自动装配(autowiring):有助于减少<PRoperty>和<constructor-arg>,让spring自动识别如何装配Bean的依赖关系。
自动检测(autodiscovery):让spring自动识别那个类要被装配成spring Bean,减少对<bean>元素的使用。
1.自动装配Bean属性
1.1 4中类型的自动装配
1.byName:把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。如果没有与属性的名字相匹配的Bean,则该属性不进行装配。
2.byType:把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。如果没有与属性的类型相匹配的Bean,则该属性不进行装配。
3.constructor:把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。
4.autodetect:先按constructor来装配,失败了按byType来装配。
1.1.1 byName自动装配
<bean id="aaa" clas=""/><bean id="bbb" class="" > <property name="aaa" ref="aaa"/></bean>如果bbb中aaa属性名字和Bean的id相同,则可以自动装配。如果bean的id和property的name相同,那么可以变为下面的这种方式:
<bean id="aaa" clas=""/><bean id="bbb" class="" autowire="byName"> </bean>如果一个Bean中属性和其他Bean的id相同就会自动装配,可是自己不需要自动装配。byName的缺点就是要假设属性名和Bean的id要一样。
1.1.2 byType自动装配
跟byName一样,只是ByType不去找属性名一样,而是去找属性的类型。
<bean id="aaa" clas="A"/><bean id="bbb" class="" > <property name="aaa" ref="aaa"/></bean>如果bbb中属性aaa为A类型,则可以byType自动装配,把autowire="byType"<bean id="aaa" clas="A"/><bean id="bbb" class="" autowire="ByType"> </bean> 如果byType找到多个Bean,那么抛出异常,应用只允许存在一个Bean与需要的自动装配的属性相匹配。byName不会找到多个,因为Bean的id是不一样的。解决的办法就是可以标识一个首选Bean,也可以让其他Bean失去资格。<bean>元素有个primary属性表示首选Bean,但是默认为true,所有的Bean都是首选Bean,所以要把非首选的Bean设置为false。<bean>的autowire-candidate属性可以设置为false表示自动装备忽略Bean的资格。
1.1.3 constructor自动装配
不需要<constructor-arg>元素,autowire为constructor。和byType有相同的局限性,也是按照类型去匹配的,一个构造器参数对应多个Bean,还有一个Bean对应多个构造器。
1.2 默认自动装配
如果所有的bean都按照同一类型自动装配,可以再<beans>元素中加default-autowire属性。这个属性默认为none,表示不使用自动装配。可以设置为byName等类型。<bean>中的autowire会覆盖default-autowire属性。<property>会覆盖自动装配的值。
autowire=“constructor”时,不能与<constructor-arg>同时存在。其他类型可以于<property>同时存在。
2. 使用注解装配
spring容器是默认禁用注解装配的。要启动,最简单的就是context命名空间的<context:annotation-config/>
1.spring自带的@Autowired注解2.JSR-330的@Inject注解
3.JSR-250的@Resource注解
2.1 @Autowired
有了这个注解,spring会按byType自动装配。这个注解可以加在setter方法上,还可以加在需要自动装配Bean的任意方法上,还可以加在构造器上。这个注解可以直接加在属性上,并删除setter方法。
这个注解必须只能有一个Bean匹配到注解的参数或属性中。没有匹配Bean或匹配多个Bean会有问题。
2.1.1可选的自动装配
默认情况下,这个注解标识的属性或参数必须是可装配的。没有Bean装配到,就会报NoSuchBeanDefinitionException。这个时候可以设置required=false来设置自动装配是可选的。没有匹配到Bean就会为null。
@Autowired(required=false)private A a; required可以用于@Autowired使用的任何地方,但是在构造器中,只能有一个构造器是required为true,其他都要设置为false。当@Autowired标注多个构造器时,spring会从满足条件的构造器中选择入参最多的构造器。2.1.2限定歧义性的依赖 有可能spring找到了多个满足条件的Bean,可以使用@Qualifier注解。
@Autowired@Qualifier("a")//指定a,默认从id找private A a; 相当于把byType转为了byName。缩小了自动装配Bean的范围。还可以在Bean中声明<bean class="A"> <qualifier value="a"/>//可以限定这个Bean为a</bean>@Qualifier("a")//可以限定这个Bean为aclass A implement B{} @Autowired是减少spring xml配置的一种方式。但是使用它的类会引入spring的特定依赖。2.2 @Inject
@Injectprivate A a; 这个注解和@Autowired一样可以自动装配,可以装配属性,方法,构造器。但是没有required属性所以装配的Bean必须存在,不存在会报错。2.2.1限定@Inject所标注的属性
@Autowired的@Qualifier与@Inject的@Named对应
@Inject@Named("a")private A a; @Qualifier注解缩小Bean的选择范围(默认使用Bean的id),@Named通过Bean的Id标识可选择的Bean。2.3在注解注入中使用表达式
@Value可以装配简单值。
@Value("jack")//这里面是一个表达式private String name;@Value("#{abc.name}")private String name;3.自动检测Bean<context:component-scan>除了完成<context:annotation-config>一样的工作外,还允许Spring自动检测Bean和定义Bean。
<context:component-scan//替代了<context:annotation-config>base-package="包">//会扫描指定的包及其子包,并找出能够自动注册的spring Bean </context:component-scan>3.1为自动检测标注Bean
默认情况下<context:component-scan>查找使用构造型注解所标注的类。
1.@Component:通用的构造型注解,表示该类为spring组件
2.@Controller:表示该类定义为spring mvc controller
3.@Repository:表示该类为数据仓库。
4.@Service:表示该类定义为服务
5.使用@Component标识的任意自定义注解
3.2过滤组件扫描
<context:component-scan>下面还有子元素<context:include-filter>和<context:exclude-filter>。只是用<context:component-scan>的情况下,spring只会去找基于注解的组件。但是还要包含一个没有注解的接口的所有实现类要怎么办。就是用<context:include-filter>
<context:component-scanbase-package="包"> <context:include-filter type="assignable" expression="xxx.abc"/></context:component-scan>type的5中类型1.annotation:扫面指定注解所标注的类,通过expression指定注解。
2.assignable:扫面派生于expression指定类型的哪些类。
3.aspectj:扫面与expression指定的aspectJ表达式匹配的类
4.custom:指定expression使用的自定义TypeFilter实现类。
5.regex:正则匹配的类。
4 使用spring基于java的配置
4.1 创建基于Java的配置
<context:component-scan>也会自动加载使用@Configuration注解所标注的类。
4.2 定义一个配置类
@Configurstion标注的类相当于<Beans>元素。可以包含一个或多个Bean。这些Bean的定义是使用@Bean注解来标注的方法。
4.3 声明一个简单Bean
@Bean public A get(){ return new B();} @Bean告知spring返回一个对象,该对象应该被注册为spring上下文的一个Bean。方法名为Bean的id。 相对于xml配置来说的一个优点就是,xml是用string类型配置的,编译期无法检查。如果重命名了一个类,或许会完了修改xml配置。4.4 使用spring的基于Java的配置进行注入
简单值注入:
@Beanpublic A get(){ return new B(12);}@Beanpublic A get(){ B b = new B(); b.setName("jack"); return B;}引用注入:@Beanpublic A get(){ return new B();}@Beanpublic C set(){ return new C(get());}这里调用get()不会调用get()方法而是调用spring上下文中的Bean。
新闻热点
疑难解答