一、前言

本文承接上一节:Spring_总结_02_依赖注入

在上一节我们了解到依赖注入的实质就是装配。

这一节我们来学习下装配Bean的相关知识。

二、Bean的装配机制

1.三种装配机制

Spring提供了三种主要的bean的装配机制:

(1)注解配置——隐式的bean发现机制和自动装配

(2)Java配置——在Java中进行显示配置

(3)XML配置——在XML中进行显示配置

2.如何选择

(1)第一考虑自动装配,显示配置越少越好。

(2)当必须要显示配置的时候,再使用类型安全并且比XML更强大的JavaConfig

(3)最后,只有当你想用使用便利的XML命名空间,并且在JavaConfig中没有同样的实现时,才应该使用XML。

这里以一个小例子来阐述组件扫描和装配。创建CompactDisc类,Spring会发现它并为其创建一个bean。然后,创建一个CDPlayer类,Spring会发现它,并将CompactDisc bean注入进来。

二、自动装配的过程

Spring从两个角度来实现自动化装配:

(1)组件扫描(component scanning):Spring 会自动发现应用上下文中所创建的bean

(2)自动装配(autowiring):Spring 自动满足bean之间的依赖

实现自动装配的过程如下:

(1)启用组件扫描: @ComponentScan

(2)声明bean      :  @Component

(3)  自动装配bean : @Autowired

三、启用组件扫描

组件扫描默认是不开启的,我们需要显示配置一下Spring,从而让它寻找带有@Component注解的类,并为其创建Bean。

配置类 CDPlayerConfig

@Configuration   //
@ComponentScan //
public class CDPlayerConfig {
}

1. 默认扫描包

1处:声明这是一个配置类

2处:开启组件扫描。默认会扫描配置类所在同级包及其子包,查找带有@Component注解的类。

2. 设置组件扫描的基础包

ComponentScan源码:

/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.context.annotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.type.filter.TypeFilter; /**
* Configures component scanning directives for use with @{@link Configuration} classes.
* Provides support parallel with Spring XML's {@code <context:component-scan>} element.
*
* <p>Either {@link #basePackageClasses} or {@link #basePackages} (or its alias
* {@link #value}) may be specified to define specific packages to scan. If specific
* packages are not defined, scanning will occur from the package of the
* class that declares this annotation.
*
* <p>Note that the {@code <context:component-scan>} element has an
* {@code annotation-config} attribute; however, this annotation does not. This is because
* in almost all cases when using {@code @ComponentScan}, default annotation config
* processing (e.g. processing {@code @Autowired} and friends) is assumed. Furthermore,
* when using {@link AnnotationConfigApplicationContext}, annotation config processors are
* always registered, meaning that any attempt to disable them at the
* {@code @ComponentScan} level would be ignored.
*
* <p>See {@link Configuration @Configuration}'s Javadoc for usage examples.
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.1
* @see Configuration
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan { /**
* Alias for {@link #basePackages}.
* <p>Allows for more concise annotation declarations if no other attributes
* are needed &mdash; for example, {@code @ComponentScan("org.my.pkg")}
* instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
*/
@AliasFor("basePackages")
String[] value() default {}; /**
* Base packages to scan for annotated components.
* <p>{@link #value} is an alias for (and mutually exclusive with) this
* attribute.
* <p>Use {@link #basePackageClasses} for a type-safe alternative to
* String-based package names.
*/
@AliasFor("value")
String[] basePackages() default {}; /**
* Type-safe alternative to {@link #basePackages} for specifying the packages
* to scan for annotated components. The package of each class specified will be scanned.
* <p>Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {}; /**
* The {@link BeanNameGenerator} class to be used for naming detected components
* within the Spring container.
* <p>The default value of the {@link BeanNameGenerator} interface itself indicates
* that the scanner used to process this {@code @ComponentScan} annotation should
* use its inherited bean name generator, e.g. the default
* {@link AnnotationBeanNameGenerator} or any custom instance supplied to the
* application context at bootstrap time.
* @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator)
*/
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; /**
* The {@link ScopeMetadataResolver} to be used for resolving the scope of detected components.
*/
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class; /**
* Indicates whether proxies should be generated for detected components, which may be
* necessary when using scopes in a proxy-style fashion.
* <p>The default is defer to the default behavior of the component scanner used to
* execute the actual scan.
* <p>Note that setting this attribute overrides any value set for {@link #scopeResolver}.
* @see ClassPathBeanDefinitionScanner#setScopedProxyMode(ScopedProxyMode)
*/
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT; /**
* Controls the class files eligible for component detection.
* <p>Consider use of {@link #includeFilters} and {@link #excludeFilters}
* for a more flexible approach.
*/
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN; /**
* Indicates whether automatic detection of classes annotated with {@code @Component}
* {@code @Repository}, {@code @Service}, or {@code @Controller} should be enabled.
*/
boolean useDefaultFilters() default true; /**
* Specifies which types are eligible for component scanning.
* <p>Further narrows the set of candidate components from everything in {@link #basePackages}
* to everything in the base packages that matches the given filter or filters.
* <p>Note that these filters will be applied in addition to the default filters, if specified.
* Any type under the specified base packages which matches a given filter will be included,
* even if it does not match the default filters (i.e. is not annotated with {@code @Component}).
* @see #resourcePattern()
* @see #useDefaultFilters()
*/
Filter[] includeFilters() default {}; /**
* Specifies which types are not eligible for component scanning.
* @see #resourcePattern
*/
Filter[] excludeFilters() default {}; /**
* Specify whether scanned beans should be registered for lazy initialization.
* <p>Default is {@code false}; switch this to {@code true} when desired.
* @since 4.1
*/
boolean lazyInit() default false; /**
* Declares the type filter to be used as an {@linkplain ComponentScan#includeFilters
* include filter} or {@linkplain ComponentScan#excludeFilters exclude filter}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter { /**
* The type of filter to use.
* <p>Default is {@link FilterType#ANNOTATION}.
* @see #classes
* @see #pattern
*/
FilterType type() default FilterType.ANNOTATION; /**
* Alias for {@link #classes}.
* @see #classes
*/
@AliasFor("classes")
Class<?>[] value() default {}; /**
* The class or classes to use as the filter.
* <p>The following table explains how the classes will be interpreted
* based on the configured value of the {@link #type} attribute.
* <table border="1">
* <tr><th>{@code FilterType}</th><th>Class Interpreted As</th></tr>
* <tr><td>{@link FilterType#ANNOTATION ANNOTATION}</td>
* <td>the annotation itself</td></tr>
* <tr><td>{@link FilterType#ASSIGNABLE_TYPE ASSIGNABLE_TYPE}</td>
* <td>the type that detected components should be assignable to</td></tr>
* <tr><td>{@link FilterType#CUSTOM CUSTOM}</td>
* <td>an implementation of {@link TypeFilter}</td></tr>
* </table>
* <p>When multiple classes are specified, <em>OR</em> logic is applied
* &mdash; for example, "include types annotated with {@code @Foo} OR {@code @Bar}".
* <p>Custom {@link TypeFilter TypeFilters} may optionally implement any of the
* following {@link org.springframework.beans.factory.Aware Aware} interfaces, and
* their respective methods will be called prior to {@link TypeFilter#match match}:
* <ul>
* <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
* <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
* <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
* <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
* </ul>
* <p>Specifying zero classes is permitted but will have no effect on component
* scanning.
* @since 4.2
* @see #value
* @see #type
*/
@AliasFor("value")
Class<?>[] classes() default {}; /**
* The pattern (or patterns) to use for the filter, as an alternative
* to specifying a Class {@link #value}.
* <p>If {@link #type} is set to {@link FilterType#ASPECTJ ASPECTJ},
* this is an AspectJ type pattern expression. If {@link #type} is
* set to {@link FilterType#REGEX REGEX}, this is a regex pattern
* for the fully-qualified class names to match.
* @see #type
* @see #classes
*/
String[] pattern() default {}; } }

其中,通过 basePackages 可用String类型来指定基础包。

通过 basePackageClasses 可用类或接口(建议使用空标记接口)来指定基础包,这些类或接口所在的包将会作为组件扫描的基础包。

示例如下:

@Configuration
@ComponentScan(basePackages = "com.ray.soundsystem")
public class CDPlayerConfig {
} @Configuration
@ComponentScan(basePackages = {"com.ray.soundsystem","com.ray.video"})
public class CDPlayerConfig {
}
public interface SoundSystemScanConfig {

}

public interface VideoScanConfig {

}

@Configuration
@ComponentScan(basePackageClasses = {SoundSystemScanConfig.class,VideoScanConfig.class})
public class CDPlayerConfig {
}

四、声明bean

1.  @Component声明bean

@Component
public class ComPactDisc { public void play(){
System.out.println("play music");
}
}

如上述代码所示,通过@Component来声明一个组件,表明该类会作为组件类,并告知Spring要为这个类创建bean。

可用以下注解来声明一个组件:

  • @Component  : 标注通用组件
  • @Controller     : 标注控制器
  • @Service        :  标注Service
  • @Respository :  标注数据访问层

通过查看源码,可知,@Controller、@Service、@Repository 能声明bean 是因为他们都组合了@Component。

以Controller为例:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller

2.为组件命名

Spring 会为所有的bean都指定一个ID,默认为类名首字母小写。

但也可通过@Component的value属性来将为bean命名,如:

@Component("compactDisc1")
public class ComPactDisc { public void play(){
System.out.println("play music");
}
}

五、自动装配bean

public class CDPlayer {

    private ComPactDisc cd;

    @Autowired
public CDPlayer( ComPactDisc cd){
this.cd =cd;
} public void play(){
cd.play();
}
}

(1)通过 @Autowired 注解,声明让Spring来自动注入符合要求的bean

(2)@Autowired 注解默认按类型匹配,可用在属性上以及任何方法上。

(3)当@Autowired 注解用在方法上时,Spring会尝试满足方法参数上所声明的依赖。假如有且只有一个bean匹配依赖需求,那么这个bean将会被装配进来。

在Spring中,只要容器中存在某个bean,就可以在另外一个Bean的声明方法的参数中注入。

用来注入bean的注解还有:

@Inject

@Resource

Spring_总结_03_装配Bean(一)_自动装配的更多相关文章

  1. Spring学习(七)bean装配详解之 【通过注解装配 Bean】【自动装配的歧义解决】

    自动装配 1.歧义性 我们知道用@Autowired可以对bean进行注入(按照type注入),但如果有两个相同类型的bean在IOC容器中注册了,要怎么去区分对哪一个Bean进行注入呢? 如下情况, ...

  2. [原创]java WEB学习笔记99:Spring学习---Spring Bean配置:自动装配,配置bean之间的关系(继承/依赖),bean的作用域(singleton,prototype,web环境作用域),使用外部属性文件

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. spring:按照Bean的名称自动装配User

    本实例将介绍如何按照Bean 的名称自动装配 User 对象! <bean> 元素的 autowire 属性负责自动装配 <bean> 标签,定义 JavaBean 的属性.这 ...

  4. SpringInAction--自动化装配Bean(隐式装配)

    关于Bean的介绍就具体不多介绍了,,, Spring在配置时候有三种方案可选 1.在xml中进行显示配置 2.在java中进行显示配置 3.隐式的Bean发现机制和自动装配 今天学习的就是自动化装配 ...

  5. Spring_总结_03_装配Bean(四)_导入与混合配置

    一.前言 本文承接上一节:Spring_总结_03_装配Bean(三)之XML配置 在典型的Spring应用中,我们可能会同时使用自动化和显示配置.同时,可能在某些场景下我们需要混合使用JavaCon ...

  6. 隐式的bean发现与自动装配机制

    使用beans.xml文件进行bean的创建和注入通常是可行的,但在便利性上Spring提供了更简单的方法--自动装配 接下来我们假设一个场景:我有若干播放器(MediaPlayer{CD播放器/MP ...

  7. Spring装配Bean之Java代码装配bean

    尽管通过组件扫描和自动装配实现Spring的自动化配置很方便也推荐,但是有时候自动配置的方式实现不了,就需要明确显示的配置Spring.比如说,想要将第三方库中的组件装配到自己的应用中,这样的情况下, ...

  8. 第2章—装配Bean—通过java代码装配bean

    通过java代码装配bean ​ 在进行显式装配的时候,有两种选型方案:java和XML配置,这里先介绍java的配置方式. 2.3.1创建配置类 先复习下上一章的配置内容: @Configurati ...

  9. Spring_总结_03_装配Bean(二)_Java配置

    一.前言 本文承接上一节:Spring_总结_03_装配Bean(一)之自动装配 上一节提到,装配Bean有三种方式,首先推荐自动装配.当自动装配行不通时,就需要采用显示配置的方式了. 显示配置有两种 ...

随机推荐

  1. 002-JVM运行时数据区【内存模型】

    一.概述 JVM定义了不同运行时数据区,他们是用来执行应用程序的.某些区域随着JVM启动及销毁,另外一些区域的数据是线程性独立的,随着线程创建和销毁. 1.1.jvm自身物理结构 1.2.java内存 ...

  2. 分布式计算开源框架Hadoop入门实践(一)

    在SIP项目设计的过程中,对于它庞大的日志在开始时就考虑使用任务分解的多线程处理模式来分析统计,在我从前写的文章<Tiger Concurrent Practice --日志分析并行分解设计与实 ...

  3. XSS - html过滤

    JS 根据白名单过滤HTML http://jsxss.com/zh/index.html   方案一: java的一个方案, 可以参考:  http://winnie825.iteye.com/bl ...

  4. 通过ip得到所在城市,以及城市所在经纬度坐标(监控系统中用的该代码,小航哥)

    监控系统中就是利用的该段代码,实现通过ip得到所在城市,以及城市所在经纬度坐标,最后得以利用echarts实现模拟迁移的效果 api官方介绍: http://lbsyun.baidu.com/inde ...

  5. Hibernate Student_Course_Score设计

    示例: 设计代码,实现在数据库中建student表.course表.和score表,展现三者关系 student表:id.name course表:id.name score表:id.score.st ...

  6. Vuex mapGetters,mapActions

    一.基本用法 1. 初始化并创建一个项目 ? 1 2 3 vue init webpack-simple vuex-demo cd vuex-demo npm install 2. 安装 vuex ? ...

  7. Django---Blog系统开发之建库

    数据库配置: #sqlite3数据库配置: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os. ...

  8. [POI2009]Wie

    题目 BZOJ 虽然是解压题但也学到了简洁的码风 做法 \(dijkstra\)跑动规 My complete code #include<bits/stdc++.h> #include& ...

  9. Sublime Text3 打开文档乱码

    一.安装包管理器使用Ctrl+~快捷键或者通过View->Show Console菜单打开命令行,粘贴如下代码 import urllib.request,os; pf = 'Package C ...

  10. Model FEP 快易播看板推播系统

    主要特色: 低成本,快速导入 透过Wi-Fi 方式推播,现场架设容易 采Web Browser 介面登入操作,简单快速 模组化版面设定,弹性调整资料呈现方式 可整合多种连线方式与外部资料库沟通 可自行 ...