资讯专栏INFORMATION COLUMN

Spring详解3.Bean的装配

endiat / 2456人阅读

摘要:的依赖关系,根据依赖关系配置完成之间的装配。的行为信息,如生命周期范围及生命周期各过程的回调函数。使用该种装配模式时,优先匹配参数最多的构造函数。如果提供了默认的构造函数,则采用否则采用进行自动装配。

点击进入我的博客 1 Spring容器与Bean配置信息
Bean配置信息

Bean配置信息是Bean的元数据信息,它由一下4个方面组成:

Bean的实现类

Bean的属性信息,如数据库的连接数、用户名、密码。

Bean的依赖关系,Spring根据依赖关系配置完成Bean之间的装配。

Bean的行为信息,如生命周期范围及生命周期各过程的回调函数。

Bean元数据信息

Bean元数据信息在Spring容器中的内部对应物是一个个BeanDefinition形成的Bean注册表,Spring实现了Bean元数据信息内部表示和外部定义之间的解耦。

Spring支持的配置方式

Spring1.0仅支持基于XML的配置,Spring2.0新增基于注解配置的支持,Spring3.0新增基于Java类配置的支持,Spring4.0则新增给予Groovy动态语言配置的支持。

2 基于XML的配置 2.1 理解XML与Schema


(1)处是默认命名空间,无命名空间前缀的元素属于默认命名空间。

(2)xsi标准命名空间,用于指定自定义命名空间的Schema文件

(3)自定义命名空间的简称,可以任意命名

(4)自定义命名空间的全称,必须在xsi命名空间为其指定空间对应的Schema文件,可以任意命名,习惯上用文档发布机构的相关网站目录。

(5)为每个命名空间指定Schema文件位置,

详解xmlns

定义:xml namespace的缩写,可译为“XML命名空间”。

作用:防止XML文档含有相同的元素命名冲突,如

既可以表示表格,又可以表示桌子。如果增加了命名空间如
就可以使两者区分开来。

使用:xmlns:namespace-prefix="namespaceURI",其中namespace-prefix为自定义前缀,只要在这个XML文档中保证前缀不重复即可;namespaceURI是这个前缀对应的XML Namespace的定义。

理解xsi:schemaLocation

xsi:schemaLocation定义了XML Namespace和对应的 XSD(Xml Schema Definition)文档的位置的关系。它的值由一个或多个URI引用对组成,两个URI之间以空白符分隔(空格和换行均可)。第一个URI是定义的 XML Namespace的值,第二个URI给出Schema文档的位置,Schema处理器将从这个位置读取Schema文档,该文档的targetNamespace必须与第一个URI相匹配。例如:


这里表示Namespace为http://www.springframework.or...://www.springframework.org/schema/context/spring-context.xsd。

2.2 使用XML装配Bean
直接装配Bean


    

id:用于表示一个Bean的名称,在容器内不能重复;不可以配置多个id。

name:用于表示一个Bean的名称,在容器内不能重复;可以配置多个名称,用,分割;id和name可以都为空,此时则可以通过获取全限定类名来获取Bean。

class:全限定类名

静态工厂方法装配

静态工厂无需创建工厂类示例就可以调用工厂类方法。

factory-method:工厂方法

public class MyBeanFactory {
    public static MyBean createMyBean() {
        return new MyBean();
    }
}
非静态工厂方法装配

非静态工厂方法必须首先定义一个工厂类的Bean,然后通过factory-bean引用工厂类实例。

factory-bean:指向定义好的工厂Bean

public class MyBeanFactory {
    public MyBean createMyBean() {
        return new MyBean();
    }
}

Bean的继承和依赖

parent:通过设置标签的parent属性,子将自动继承父的配置信息。

depends-on:通过设置标签的depends-on属性,Spring允许显示的设置当前Bean前置依赖的Bean,确保前置依赖的Bean在当前Bean实例化之前已经创建好。

自动装配autowire

元素提供了一个default-autowire属性可以全局自动匹配,默认为no。元素提供了一个指定自动装配类型的autowire属性,可以覆盖元素的default-autowire属性,该属性有如下选项:

自动装配类型 说明
no 显式指定不使用自动装配。
byName 如果存在一个和当前属性名字一致的 Bean,则使用该 Bean 进行注入。如果名称匹配但是类型不匹配,则抛出异常。如果没有匹配的类型,则什么也不做。
byType 如果存在一个和当前属性类型一致的 Bean ( 相同类型或者子类型 ),则使用该 Bean 进行注入。byType 能够识别工厂方法,即能够识别 factory-method 的返回类型。如果存在多个类型一致的 Bean,则抛出异常。如果没有匹配的类型,则什么也不做。
constructor 与 byType 类似,只不过它是针对构造函数注入而言的。如果当前没有与构造函数的参数类型匹配的 Bean,则抛出异常。使用该种装配模式时,优先匹配参数最多的构造函数。
default 根据 Bean 的自省机制决定采用 byType 还是 constructor 进行自动装配。如果 Bean 提供了默认的构造函数,则采用 byType;否则采用 constructor 进行自动装配。
通过util命名空间配置集合类型的Bean


2.3 使用XML依赖注入
属性配置

Bean有一个无参数的构造器

属性有对应的Setter函数

属性命名满足JavaBean的属性命名规范


    
构造方法

constructor-arg中的type和index可以没有,只要能保证可以唯一的确定对应的构造方法即可

type中基本数据类型和对应的包装类不能通用

循环依赖:如果两个Bean都采用构造方法注入,而且都通过构造方法入参引用对方,就会造成循环依赖导致死锁。


    
    
2.4 注入参数
字面值

基本数据类型及其封装类、String都可以采取字面值注入。

特殊字符可以使用节或者转义序列

引用其他Bean

元素可以通过以下三个属性引用容器中的其他Bean:

bean:通过该属性可以引用同一容器或父容器的Bean,这是最常见的形式。

local:通过该属性只能引用同一配置文件中定义的Bean,它可以利用XML解析器自动检验引用的合法性,以便在开发编写配置时能够及时发现并纠正配置的错误。

parent:引用父容器中的Bean,如的配置说明car的Bean是父容器中的Bean。

内部Bean

内部Bean只会被当前Bean引用,不会被容器中其他的Bean引用

内部Bean即使提供了id、name、scope也会被忽略,Scope默认为prototype类型。

    
        
    

    
        
            
            
                
            
        
    
null值

使用代表null值

级联属性

Spring支持级联属性如prop.value,而且支持多层级联属性

级联属性必须有初始值,否则会抛出NullValueInNestedPathException

public class MyBean {
    // 必须初始化
    private Prop prop = new Prop();

    public Prop getProp() {
        return prop;
    }

    public void setProp(Prop prop) {
        this.prop = prop;
    }
}
    
        
    
集合类型属性

List、Set、Map:通过等标签可以设置List、Set、Map的属性

Properties:可以通过等标签设置Properties的属性,Properties属性的键值都只能是字符串。

集合合并:子Bean可以继承父Bean的同名属性集合元素,并且使用merge属性选择是否合并,默认不合并。

    
        
            
                1314
            
        
    

    
        
            
                520
            
        
    
2.5 多配置文件整合

可以通过ApplicationContext加载多个配置文件,此时多个配置文件中的是可以互相访问的。

可以通过XML中的将多个配置文件引入到一个文件中,这样只需要加载一个配置文件即可。

2.6 Bean的作用域
类型 说明
singleton 在Spring IoC容器中仅存在一个Bean实例,Bean以单实例的方式存在
prototype 每次从容器中调用Bean时,都返回一个新的实例
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP session共享一个Bean,不同的HTTP session使用不同的Bean,该作用域仅适用于WebApplicationContext环境
globalSession 同一个全局Session共享一个Bean,一般用于Portlet环境,该作用域仅适用于WebApplicationContext环境
singleton作用域

无状态或者状态不可变的类适合使用单例模式

如果用户不希望在容器启动时提前实例化singleton的Bean,可以使用lazy-init属性进行控制

如果该Bean被其他需要提前实例化的Bean所引用,那么Spring将会忽略lazy-init的设置

prototype作用域

设置为scope="prototype"之后,每次调用getBean()都会返回一个新的实例

默认情况下,容器在启动时不会实例化prototype的Bean

Spring容器将prototype的Bean交给调用者后就不再管理它的生命周期

Web应用环境相关的Bean作用域

见后续章节

作用域依赖的问题

见后续章节

3 FactoryBean

由于实例化Bean的过程比较负责,可能需要大量的配置,这是采用编码的方式可能是更好的选择。Spring提供了FactoryBean工厂类接口,用户可以实现该接口定制实例化Bean的逻辑。当配置文件中的class属性配置的是FactoryBean的子类时,通过getBean()返回的不是FactoryBean本身,而是getObject()方法所返回的对象,相当于是FactoryBean#getObject()代理了getBean()方法

T getObject() throws Exception;:返回由FactoryBean创建的Bean实例,如果isSingleton()返回的是true,该实例会放到Spring容器的实例缓存池中。

Class getObjectType();:返回该FactoryBean创建的Bean的类型

boolean isSingleton();:创建的Bean是singleton的还是prototype

/**
 * 实现,分割的方式配置 KFCCombo 属性
 */
public class KFCFactoryBean implements FactoryBean {
    private String prop;

    public String getProp() {
        return prop;
    }

    // 接受,分割的属性设置信息
    public void setProp(String prop) {
        this.prop = prop;
    }

    // 实例化KFCCombo
    public KFCCombo getObject() throws Exception {
        KFCCombo combo = new KFCCombo();
        String[] props = prop.split(",");
        combo.setBurger(props[0]);
        combo.setDrink(props[1]);
        return combo;
    }

    public Class getObjectType() {
        return KFCCombo.class;
    }

    // true则放进容器缓存池,false则每次都调用getObject()方法返回新的对象
    public boolean isSingleton() {
        return false;
    }
}
    
        
    
4 基于注解的配置 4.1 支持的注解

@Component:在Bean的实现类上直接标注,可以被Spring容器识别
@Repository:用于对DAO实现类进行标柱
@Service:用于对Service实现类进行标注
@Controller:用于对Controller实现类进行标注

4.2 扫描注解定义对Bean

Spring提供了一个context命名空间,用于扫描以注解定义Bean的类。




    
base-package属性

指定一个需要扫描的基类包,Spring容器会扫描这个包下的所有类,并提取标注了相关注解的Bean。

resource-pattern属性

如果不希望扫描base-package下的所有类,可以使用该属性提供过滤

该属性默认是**/*.class,即基包下的所有类

:表示要排除的目标类

:表示要包含的目标类

可以有多个上述两个子元素;首先根据exclude-filter列出需要排除的黑名单,然后再根据include-filter流出需要包含的白名单。

类别 示例 说明
annotation com.ankeetc.XxxAnnotation 所有标注了XxxAnnotation的类。该类型采用目标类是否标志了某个注解进行过滤。
assignable com.ankeetc.XxService 所有继承或扩展XXXService的类。该类型采用目标类是否继承或者扩展了某个特定类进行过滤
aspectj com.ankeetc..*Service+ 所有类名以Service结束的类及继承或者扩展他们的类。该类型采用AspectJ表达式进行过滤
regex com.ankeetc.auto..* 所有com.ankeetc.auto类包下的类。该类型采用正则表达式根据目标类的类名进行过滤
custom com.ankeetc.XxxTypeFilter 采用XxxTypeFilter代码方式实现过滤规则,该类必须实现org.springframework.core.type.TypeFilter接口
use-default-filters属性

use-default-filters属性默认值为true,表示会对标注@Component、@Controller、@Service、@Reposity的Bean进行扫描。

如果想仅扫描一部分的注解,需要将该属性设置为false。



    
4.3 自动装配
@Component
public class KFCCombo {
    @Autowired
    private PepsiCola cola;

    @Autowired
    private Map colaMap;

    @Autowired
    private List burgerList;

    private ZingerBurger burger;
    @Autowired
    public void setBurger(@Qualifier(value = "zingerBurger") ZingerBurger burger) {
        this.burger = burger;
    }

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:/beans.xml"});

        KFCCombo combo = context.getBean(KFCCombo.class);
    }
}

interface Cola {}

@Order(value = 1)
@Component
class CocaCola implements Cola {}

@Order(value = 2)
@Component
class PepsiCola implements Cola {}

@Component(value = "zingerBurger")
class ZingerBurger {
}
@Autowired注解

使用该注解可以按类型自动装配对应的Bean

没有找到对应的Bean则会抛出NoSuchBeanDefinitionException异常

使用required=false属性可以设置即使找不到对应的Bean(即为null)也不会抛出异常

@Autowired可以对类成员变量及方法入参进行标注

@Quaifiler

如果容器中有一个以上匹配的Bean时,可以按照Bean名字查找对应的Bean

@Quaifiler需要与@Autowired配合使用

对集合类进行标注

可以使用@Autowired对集合类进行标注,Spring会讲容器中按类型匹配对所有Bean注入进来

可以使用@Order指定加载顺序,值越小的越先加载

@Lazy延迟加载

可以使用@Lazy实现延迟加载,不会立即注入属性值,而是延迟到调用此属性对时候才会注入属性值。

@Resource和@Inject

Spring支持JSR-250中@Resource注解和JSR-330的@Inject注解

@Resource采用的是按照名称加载的方式,它要求提供一个Bean名称的属性,如果属性为空,则自动采用标注处的变量名或方法名作为Bean的名称。

@Inject是按照类型匹配注入Bean的。

由于这两个注解功能没有@Autowired功能强大,一般不需要使用。

4.4 Bean作用范围及生命周期

注解配置的Bean默认作用范围为singleton,可以使用@Scope显示指定作用范围

可以使用@PostConstruct和@PreDestroy注解来达到init-method和destroy-method属性的功能。

@PostConstruct和@PreDestroy注解可以有多个

5 基于Java类的配置 5.1 @Configuration注解

JavaConfig是Spring的一个子项目,旨在通过Java类的方式提供Bean的定义信息。

普通的POJO标注了@Configuration注解,就可以被Spring容器提供Bean定义信息。

@Configuration注解本身已经标注了@Component注解,所以任何标注了@Configuration的类都可以作为普通的Bean。

5.2 @Bean注解

@Bean标注在方法上,用于产生一个Bean

Bean的类型由方法的返回值的类型确定,Bean名称默认与方法名相同,也可以显示指定Bean的名称。

可以使用@Scope来控制Bean的作用范围。

5.3 启动Spring容器
通过@Configuration类启动Spring容器

可以直接设置容器启动要注册的类

可以向容器中注册新的类,注册了新的类要记得refresh

可以通过@Import将多个配置类组装称一个配置类

public class Main {
    public static void main(String[] args) {
        // (1)可以直接设置容器启动要加载的类
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DaoConfig.class);
        // (2)可以向容器中注册新的类
        ((AnnotationConfigApplicationContext) applicationContext).register(ServiceConfig.class);
        // (3)注册了新的类要记得refresh
        ((AnnotationConfigApplicationContext) applicationContext).refresh();
    }
}

@Configuration
class DaoConfig {
    @Bean
    public String getStr() {
        return "1314";
    }
}

@Configuration
@Import(DaoConfig.class)
// (4)可以通过@Import将多个配置类组装称一个配置类
class ServiceConfig {
}
通过XML配置文件引用@Configuration的配置

标注了@Configureation的配置类本身也是一个bean,它可以被Spring的扫描到。如果希望将此配置类组装到XML配置文件中,通过XML配置文件启动Spring容器,仅在XML文件中通过扫描到相应的配置类即可。

通过@Configuration配置类引用XML配置信息

在标注了@Configuration的配置类中,可以通过@ImportResource引入XML配置文件。

@Configuration
@ImportResource("classpath:beans.xml")
public class Config {
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72883.html

相关文章

  • spring mvc 常用注解标签详解【转载】

    摘要:分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了注解。的作用相当于,只不过按照自动注入。作用该注解用于将的方法返回的对象,通过适当的转换为指定格式后,写入到对象的数据区。用于注解层,在类上面注解。 原文地址 Controller 在SpringMVC中,控制器Controller负责处理由DispatcherServlet分发的请求,它把用户请求的数据经过业务处理层处理...

    Kylin_Mountain 评论0 收藏0
  • Spring核心组件剖析

    摘要:本文主要探讨的三大核心组件。的核心组件有很多,但真正构成其骨骼的,是,和。因此,的核心思想常常被称作,面向编程。的重要组成部分之一是。总结本文主要总结了构成骨骼框架的三大核心组件及其之间的联系,以及对三者实现原理理解的一些心得体会。 简介 Spring框架如今已成为服务端开发框架中的主流框架之一,是web开发者的利器。然而,真正让人着迷的,还是与其实现相关的 原理,设计模式以及许多工...

    springDevBird 评论0 收藏0
  • Java深入-框架技巧

    摘要:从使用到原理学习线程池关于线程池的使用,及原理分析分析角度新颖面向切面编程的基本用法基于注解的实现在软件开发中,分散于应用中多出的功能被称为横切关注点如事务安全缓存等。 Java 程序媛手把手教你设计模式中的撩妹神技 -- 上篇 遇一人白首,择一城终老,是多么美好的人生境界,她和他历经风雨慢慢变老,回首走过的点点滴滴,依然清楚的记得当初爱情萌芽的模样…… Java 进阶面试问题列表 -...

    chengtao1633 评论0 收藏0
  • 第一章--Spring之旅

    摘要:两种方式来表示的应用上下文。日志,事务管理和安全这样的系统服务经常融入到具有核心业务逻辑的组件中去,这些系统服务通过被称为横切关注点。容器使用管理构成应用的组件,他会创建相互协作的组件之间的关联。的生命周期四俯瞰的风景线模块,,,, 完整代码请见:https://github.com/codercuixi...为了降低Java开发的复杂性,Spring采用了以下4种策略: 基于poj...

    pkwenda 评论0 收藏0

发表评论

0条评论

endiat

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<