`
Adan-Chiu
  • 浏览: 21666 次
社区版块
存档分类
最新评论

装配Spring Bean

 
阅读更多
1.依赖注入的3种方式
   在实际环境中实现IoC容器的方式主要分为两大类,一类是依赖查找,依赖查找是通过依赖定位,把对应的资源查找回来;另一类是依赖注入,而spring主要使用的是依赖注入。一般而言,依赖注入可以分为3种方式。
  • 构造器注入
  • setter注入
  • 接口注入


构造器注入和setter注入是主要的方式,而接口注入是从别的地方注入的方式。

1.1构造器注入
   构造器注入依赖构造方法的实现
<bean id="departmentService" class="com.wise.tiger.service.impl.DepartmentServiceImpl" init-method="init" destroy-method="destory">
        <!--使用类构造器实例化Bean -->
   <constructor-arg name="departmentName" value="生产部"/>
</bean>


    constructor-arg用于定义类构造方法的参数,其中index用于定义参数的位置,而value则是设置值,也可以通过参数名name进行注入。
    这样注入还是比较简单的,但是缺点也很明显,由于这里的参数比较少,所以可读性还是比较不错的,但是如果参数较多,这种构造方法就比价复杂了,这个时候就要考虑setter注入了

1.2 使用setter注入
    setter注入是spring中最主流的注入方式,利用javaBean规范所定义的setter方法来完成注入,灵活且可读性高。它是通过反射技术实现的
<bean id="departmentService" class="com.wise.tiger.service.impl.DepartmentServiceImpl" init-method="init" destroy-method="destory">
   <property name="departmentName" value="生产部"/>
</bean>


1.3 接口注入
    参考另一篇博文

2.装配Bean概述
     如何将Bean装配到IoC容器中,在spring中提供了三种方法进行配置
  • 在xml中显式配置
  • 在java的接口和类中实现配置
  • 隐式Bean的发现机制和自动装配原则

   在现实工作中,这三种方式都会用到,并且经常混合使用。建议优先级如下
(1)基于约定优于配置的原则,最优先的应该是隐式Bean的发现机制和自动装配原则。这样的好处是减少程序开发者的决定权,简单又不失灵活。
(2)在没有办法使用自动装配原则的情况下应该优先考虑Java接口和类中实现配置。这样的好处是避免xml配置的泛滥,也更为容易
(3)上述方法都无法使用的情况下,那么只能选择xml去配置spring IoC容器,比如第三方的类库。
    通俗来讲,当配置的类是你自身开发的工程,那么应该考虑java配置为主,而java配置又分为自动装配和Bean名称装配。在没有歧义的基础上,优先使用自动装配,这样可以减少大量的xml配置。如果所需配置的类并不是你的工程开发的,那么建议使用xml的方式。

3.通过xml装配Bean
引入对应的xml模式(xsd)文件
<?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">
</beans>

3.1.装配简易值
<bean id="departmentService" class="com.wise.tiger.service.impl.DepartmentServiceImpl">  
   <property name="departmentName" value="生产部"/>  
</bean> 

  • id:spring找到这个Bean的编号,不是一个必须的属性,如果没有指定,spring采用"权限定名#{number}的格式生成编号。
  • class:一个类的全限定名
  • property:定义类中的属性


3.2 装配集合
<bean id="personService" class="com.wise.tiger.service.impl.PersonServiceImpl">
        <property name="personName" value="张三丰"/>
        <property name="hobbys">
            <array>
                <value>看美女</value>
                <value>看小说</value>
                <value>看电影</value>
            </array>
        </property>
        <property name="hobbyList">
            <list>
                <value>hobby-list-1</value>
                <value>hobby-list-2</value>
                <value>hobby-list-3</value>
                <value>hobby-list-4</value>
            </list>
        </property>
        <property name="hobbySet">
            <set>
                <value>hobby-set-1</value>
                <value>hobby-set-2</value>
                <value>hobby-set-3</value>
            </set>
        </property>
        <property name="intro">
            <map>
                <entry key="name" value="peppa"/>
                <entry key="age" value="5"/>
                <entry key="hobby" value="我喜欢乒,我喜欢乓,我喜欢suzy和我一起跳"/>
            </map>
        </property>
        <property name="prop">
            <props>
                <prop key="prop1">prop-value-1</prop>
                <prop key="prop2">prop-value-2</prop>
            </props>
        </property>
    </bean>

3.3.命名空间装配
   先引入对应的命名空间和xml模式(xsd)文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
       <bean id="personService1" class="com.wise.tiger.service.impl.PersonServiceImpl"
        p:personName="suzy"/>
<beans/>
       <bean id="personService2" class="com.wise.tiger.service.impl.PersonServiceImpl"
        c:personName="suzy"/>
<beans/>

c:personName代表构造方法参数名为personName的参数,也可以采用c:_0表示构造方法的第一个参数
p代表引用属性,p:personName="suzy"以suzy为值,使用setPersonName方法设置。
<?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:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">

<util:list id="emails">
    <value>pechorin@hero.org</value>
    <value>raskolnikov@slums.org</value>
    <value>stavrogin@gov.org</value>
    <value>porfiry@gov.org</value>
</util:list>

<util:map id="emails">
    <entry key="pechorin" value="pechorin@hero.org"/>
    <entry key="raskolnikov" value="raskolnikov@slums.org"/>
    <entry key="stavrogin" value="stavrogin@gov.org"/>
    <entry key="porfiry" value="porfiry@gov.org"/>
</util:map>

<util:set id="emails">
    <value>pechorin@hero.org</value>
    <value>raskolnikov@slums.org</value>
    <value>stavrogin@gov.org</value>
    <value>porfiry@gov.org</value>
</util:set>

<util:properties id="jdbcConfiguration" location="classpath:jdbc-production.properties"/>

</beans>

通过命名空间定义set,list,map,properties等。

4.通过注解装配Bean
    更多的时候已经不再推荐使用xml的方式去装配Bean,更多的时候会考虑使用注解(annotation)的方式去装配Bean。使用注解可以减少xml的配置,注解功能更为强大,它既能实现xml的功能,也提供了自动装配的功能,程序猿所需要做的决断就减少了,更加有利于对程序的开发,这就是“约定优于配置”的开发原则。
   在Spring中,提供了两种方式来让 Spring IoC容器发现Bean。
  • 组件扫描:通过定义资源的方式,让Spring IoC容器扫描对应的包,从而把Bean装配进来。
  • 自动装配:通过注解定义,使得一些依赖关系可以通过注解完成

   1.使用@Component装配Bean
@Component
public class EmilSender {
	
}

    注解@Component代表Spring IoC容器会把这个类扫描成Bean实例。而其中的value属性代表这个实例在Spring中的id,相当于xml方式定义的Bean的id,也可以简写成@Component(""),也可以直接写成@Component,id即为类的简单名称首字母小写。
    spring主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有所差异:

  • @Component:可以用于注册所有bean
  • @Repository:主要用于注册dao层的bean
  • @Controller:主要用于注册控制层的bean
  • @Service:主要用于注册服务层的bean


   2.自动装配@Autowired
    当Spring装配Bean属性时,有时候非常明确,就是需要将某个Bean的引用装配给指定属性。比如,如果我们的应用上下文中只有一个org.mybatis.spring.SqlSessionFactoryBean类型的Bean,那么任意一个依赖SqlSessionFactoryBean的其他Bean就是需要这个Bean。毕竟这里只有一个SqlSessionFactoryBean的Bean。
   为了应对这种明确的装配场景,Spring提供了自动装配(autowiring)。与其显式的装配Bean属性,为何不让Spring识别出可以自动装配的场景。
   当涉及到自动装配Bean的依赖关系时,Spring有多种处理方式。因此,Spring提供了4种自动装配策略。
<bean id="" class="" autowire="no|byName|byType|constructor|autodetect"></bean>
  • no:不进行自动装配,手动设置Bean的依赖关系
  • byName:根据Bean的名字进行自动装配
  • byType:根据Bean的类型进行自动装配
  • constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误
  • autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配

   默认自动装配:在根元素Beans上增加属性default-autowire="byType"

    Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有 @Autowired 注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。IoC容器有时候会寻找失败,在默认情况下失败就会抛出异常,可以通过配置项required来改变它,比如:@Autowired(required=false)
@Service
public class PersonServiceImpl implements PersonSerivce {
	@Autowired
	private PersonDao dao;
}

   4.3.自动装配的歧义性
    通常bean的自动装配能够给我们提供很大的方便,它会减少装配应用程序组件时所需要的显示配置的麻烦。不过,仅有一个bean匹配所需的结果时,自动装配才是有效的。如果符合条件的bean不只一个,这时就会阻碍Spring自动装配属性、构造器参数或方法参数。
    为了消除歧义性,Spring提供了两个注解@Primary和@Qualifier。
    标识首选的bean,某个接口有多个实现类,可以在某个实现类上标注@Primary,当出现歧义时,Spring会使用首选的bean,其他的会忽略,但是如果这个接口有两个实现类都标注了@Primary的话,那么又出现歧义了,所以@Primary只能标注在一个接口的一个实现类上
@Component
@Primary
public class PersonServiceImpl1 implements PersonService{

}

--------------------------------------------------------
<bean id="personService1" class="com.wise.serivce.impl.PersonServiceImpl1 " primary="true" />
--------------------------------------------------------
@Bean
@Primary
public PersonService getPersonService(){

    return new PersonServiceImpl1();
}

可以使用@Qualifier("beanName")明确指定要注入的是哪个bean
  4.4.装配带有参数的构造方法类
@Service
public class PersonServiceImpl {
	private PersonDao dao;
	public PersonServiceImpl(@Autowired PersonDao dao) {
		this.dao = dao;
	}
}

@Autowired和@Qualifier这两个注解可以支持到参数。
   4.5.使用@Bean装配Bean
以上大部分都是通过@Component装配Bean,但是@Component只能注解在类上,不能注解到方法上,@Bean可以注解到方法上,将方法返回的对象作为Spring的Bean存放在IoC容器中,如没指定name,bean的id默认为方法名。
@Bean
public DataSource devDataSource(@Value("${driverClassName}") String driverClassName,
		@Value("${url}") String url,
		@Value("${username}") String username,
		@Value("${password}") String password,
		@Value("${connectionProperties}") String connectionProperties) throws Exception {
	var prop = new Properties();
	prop.put("driverClassName", driverClassName);
	prop.put("url", url);
	prop.put("username", username);
	prop.put("password", password);
	prop.put("connectionProperties", connectionProperties);
	return BasicDataSourceFactory.createDataSource(prop);
}

  4.6.注解自定义Bean的初始化和销毁方法
@Bean(name="", initMethod="init",destroyMethod="destroy")

@Bean的配置项中包含4个配置项。
  • name:字符串数组,允许配置多个BeanName,没有配置默认为方法名。
  • autowire:标志是否是一个引用的Bean对象,默认值是Autowire.NO
  • initMethod:自定义初始化方法
  • destroyMethod:自定义销毁方法

5.装配的混合使用
        spring-data.xml->使用xml配置数据源
<context:property-placeholder location="classpath:jdbc.properties"/>
    <!--定义数据源:Druid数据源默认是自动提交事务,需要关闭自动提交 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
      <property name="driverClassName" value="${driverClassName}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${jdbc.username}"/>
      <property name="password" value="${password}"/>
      <property name="connectionProperties" value="${connectionProperties}"/>
      <property name="defaultAutoCommit" value="${defaultAutoCommit}"/>
</bean>

      这种方式我们不需要去了解第三方的更多细节,也不需要过多的java代码,尤其是不用try...catch...finally...语句去处理它们,相对与@Bean的注入会更好一些,也更为简单,所以对于第三方的包或者其它外部的接口,建议使用xml的方式。
    spring同时支持这两种形式的装配,可以自由选择,无论是xml还是注解都是将bean装配到Spring IoC容器中,这样就可以通过spring IoC容器去管理各类资源了,首先使用@ImportResource,引入spring-data.xml所定义的类容。

@Configuration
@ComponentScan(basePackages = "com.wise.tiger")
@ImportResource(locations = {"classpath:spring-data.xml"})
public class ApplicationConfig {

}

  当需要使用到数据源DataSource时,就可以使用@Autowired或者@Resource进行注入
6.使用Profile
    在软件开发过程中,敏捷开发模式很常见,一种时间控制的迭代式实现和发布软件的方法。那么可能是开发人员使用一套环境,而测试人员使用另外一套环境,而这两天系统的数据库是不一样的,毕竟测试人员也需要花费很多时间去构建测试数据,可不想老是被开发人员修改那些测试数据,这样就有了在不同环境中进行切换的需求了。spring也会对这样的场景进行支持。
  6.1.使用@Profile配置
@Bean(name = "devDataSource") 
@Profile("dev")
public DataSource getDataSource() {
	var dataSource = new BasicDataSource();
	dataSource.setUrl(url);
	dataSource.setUsername(username);
	dataSource.setDriverClassName(driverClassName);
	dataSource.setPassword(password);
	dataSource.setMaxTotal(maxTotal);
	dataSource.setMaxIdle(maxIdle);
	dataSource.setMaxWaitMillis(maxWaitMillis);
	dataSource.setConnectionProperties(connectionProperties);
	dataSource.setAutoCommitOnReturn(defaultAutoCommit);
	return dataSource;
}
@Bean(name = "testDataSource") 
@Profile("test")
public DataSource getDataSource1(
		@Value("${driverClassName}") String driverClassName,
		@Value("jdbc:mysql:///test") String url,
		@Value("${username}") String username,
		@Value("${password}") String password) {
	var dataSource = new BasicDataSource();
	dataSource.setUrl(url);
	dataSource.setUsername(username);
	dataSource.setDriverClassName(driverClassName);
	dataSource.setPassword(password);
	return dataSource;
}

   2.使用xml定义Profile
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="...">

    <!-- other bean definitions -->

    <beans profile="development">
        <jdbc:embedded-database id="dataSource">
            <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
            <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
        </jdbc:embedded-database>
    </beans>

    <beans profile="production">
        <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
    </beans>
</beans>

   3.启动Profile
  当启动java配置或者xml配置profile时,Bean并不会被加载到IoC容器中。需要自行激活Profile。激活方法有5种
  • 在使用SpringMVC的情况下可以配置Web上下文参数,或者DispatchServlet参数
  • 作为JNDI条目
  • 配置环境变量
  • 配置JVM启动参数
  • 在集成测试环境中使用@ActiveProfiles

常用激活:
    在测试代码中激活Profile,如果是开发人员进行测试,那么可以使用注解@ActiveProfiles进行定义

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring-profile.xml")
@ActiveProfiles("dev")
public class TestActiveProfile {
}


   在测试代码中可以加入@ActiveProfiles来指定加载哪个Profile,这样程序就会自己去加载对应的profile了。但是毕竟不是什么时候都是在测试代码中运行,有些时候要在服务器上运行,那么这个时候可以配置java虚拟机的启动项,关于指定profile的参数存在两个。
spring.profiles.active 启动的
spring.profiles.default 默认的

可以配置JVM的参数来启动对应的Profile,比如需要启动test:

JAVA_OPTS="-Dspring.profiles.active=test" 

   在大部分情况下需要启动web服务器,通常可以在 web.xml 中定义全局 servlet 上下文参数 spring.profiles.default 实现,代码如下
 
<!-- 配置spring的默认profile -->  
<context-param>  
    <param-name>spring.profiles.default</param-name>  
    <param-value>test</param-value>  
</context-param> 


7. 加载属性(properties)文件
在开发过程中,配置文件往往就是那些属性(properties)文件,比如:
driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/db_book
username = peppa
password = pedro

########## dbcp连接池基本属性 #############
# 初始化连接
initialSize=20
#最大连接数量,设 0 为没有限制
maxTotal = 0
#最大空闲连接
maxIdle = 10
#最小空闲连接
minIdle = 3
#超时等待时间以毫秒为单位
maxWaitMillis = 1000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties = serverTimezone=UTC;useSSL=false;useUnicode=true;characterEncoding=utf-8

#指定由连接池所创建的连接的自动提交(auto-commit)状态。如果指定为false表示关闭自动提交
defaultAutoCommit = false

#driver default 指定由连接池所创建的连接的只读(read-only)状态。默认false
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
#defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
#defaultTransactionIsolation = REPEATABLE_READ

使用properties是十分常见的情景,可以有效减少硬编码,有效提高运维人员的操作便利性。

   7.1.使用注解方式加载属性文件
    Spring提供了@PropertySource来加载属性文件
  • name:字符串,属性配置的名称
  • value:字符串数组,可以配置多个属性文件
  • ignoreResourceNotFound:boolean值,默认值为false:如果属性文件没有找到是否忽略处理。
  • encoding:编码

@Configuration
@ComponentScan(basePackages = "com.wise.tiger")
@PropertySource(value = "classpath:dbcp-config.properties",ignoreResourceNotFound = true,encoding = "UTF-8")
public class ApplicationConfig {}


使用注解@Value和占位符去解析属性占位符
@Configuration
@ComponentScan(basePackages = "com.wise.tiger")
@PropertySource(value = "classpath:dbcp-config.properties",ignoreResourceNotFound = true,encoding = "UTF-8")
public class ApplicationConfig {
	@Value("${url}")
	private String url;
	@Value("${username}")
	private String username;
	@Value("${password}")
	private String password;
	@Value("${driverClassName}")
	private String driverClassName;
	@Value("${maxTotal}")
	private int maxTotal;
	@Value("${maxWaitMillis}")
	private long maxWaitMillis;
	@Value("${maxIdle}")
	private int maxIdle;
	@Value("${defaultAutoCommit}")
	private boolean defaultAutoCommit;
	@Value("${connectionProperties}")
	private String connectionProperties;
	
	@Bean(name = "dataSource") 
	public DataSource getDataSource() {
		var dataSource = new BasicDataSource();
		dataSource.setUrl(url);
		dataSource.setUsername(username);
		dataSource.setDriverClassName(driverClassName);
		dataSource.setPassword(password);
		dataSource.setMaxTotal(maxTotal);
		dataSource.setMaxIdle(maxIdle);
		dataSource.setMaxWaitMillis(maxWaitMillis);
		dataSource.setConnectionProperties(connectionProperties);
		dataSource.setAutoCommitOnReturn(defaultAutoCommit);
		return dataSource;
	}
	
}

   7.2.使用xml方式加载属性文件
<context:property-placeholder location="classpath:dbcp-config.properties" ignore-resource-not-fount="true"/>

    ignore-resource-not-fount属性代表是否允许文件不存在,当默认值为false时,不允许文件不存在,如果不存在,spring会抛出异常
    location是一个配置文件路径的选项,可以配置多个或者单个文件,多个文件之间用,分割。如果系统中存在很多文件,那么属性location就要配置长长的字符串了,不过还有其它的xml方式可以进行配置:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <!-- 字符串数组,可以配置多个属性文件-->
     <property name="locations">
         <array>
            <value>classpath:jdbc.properties</value>
            <value>classpath:message.properties</value>
         </array>
     </property>
     <property name="ignoreResourceNotFount" value="true"/>
</bean>

8 条件化装配Bean
   在某些条件下不需要去装配Bean,比如当属性文件中没有数据源的基础配置的时候就不要去创建数据源。这时就需要通过条件化去判断。Spring提供了@Conditional去配置,通过配置一个或多个类,只是这些类需要实现接口Condition。
@Bean(name = "dataSource") 
@Conditional(DataSourceCondition.class)
public DataSource getDataSource(
		@Value("${driverClassName}") String driverClassName,
		@Value("${url}") String url,
		@Value("${username}") String username,
		@Value("${password}") String password) {
	var dataSource = new BasicDataSource();
	dataSource.setUrl(url);
	dataSource.setUsername(username);
	dataSource.setDriverClassName(driverClassName);
	dataSource.setPassword(password);
	return dataSource;
}

通过@Value往参数里注入了对应属性文件的配置,但是我们没有办法确定这些数据源连接池的属性是否在属性文件中已经配置完整,如果是不充足的属性配置,则会引起创建失败,为此要判断属性文件的配置是否满足才能继续创建Bean。通过@Conditional去引入了一个条件判断类----DataSourceCondition,由它来进行判断。

package com.wise.tiger;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * 条件判断,需要实现Condition接口
 */
public class DataSourceCondition implements Condition {

	/**
	 * 判断属性文件中是否配置了数据源的相关参数
	 * @param context:通过它可以获取spring的运行环境
	 * @param metadata:通过它可以获得关于该Bean的注解信息
	 * @return true:创建对应的Bean,false:不会创建
	 */
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		//获取Spring的运行环境
		var env = context.getEnvironment();
		//判断是否存在关于数据源的基础配置
		return env.containsProperty("driverClassName")
				&& env.containsProperty("url")
				&& env.containsProperty("username")
				&& env.containsProperty("password");
	}
}


9 Bean的作用域
   在默认情况下,Spring IoC容器只会对一个Bean创建一个实例。bean可以定义为部署在多个作用域中的一个作用域中。Spring框架支持六个作用域,其中四个作用域仅在使用Web感知的ApplicationContext时可用。还可以创建自定义范围。
singleton 单例,默认选项,在整个应用中,spring只为其生成一个Bean的实例
prototype 原型,当每次注入或者通过IoC容器获取Bean时,Spring都会为它创建一个新的实例
request 请求,web应用中使用,一次请求创建一个Bean的实例,不同的请求会创建不同的实例
session 会话,web应用中使用,会话过程中创建一个Bean的实例
application servletContext,web应用中使用,单个bean定义范围扩展到servletContext的生命周期
webscoket servletContext,web应用中使用,单个bean定义范围扩展到websocket的生命周期

可以采用@Scope注解声明Bean的作用域
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

10 使用SPring表达式(Spring EL)
Spring还提供了更灵活的注入方式,那就是Spring表达式,Spring表达式语言(简称spel)是一种功能强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于统一的EL,但提供了其他特性,最显著的是方法调用和基本的字符串模板功能:
  • 使用Bean的id来引用Bean
  • 调用指定对象的方法和访问对象的属性
  • 进行运算
  • 提供正则表达式进行匹配
  • 集合配置

10.1 Spring EL相关类
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'"); 
String message = (String) exp.getValue();//The value of the message variable is 'Hello World'.
exp = parser.parseExpression("'Hello World'.concat('!')");
message = (String) exp.getValue(); //The value of message is now 'Hello World!'.


// Create and set a calendar
GregorianCalendar c = new GregorianCalendar();
c.set(1856, 7, 9);

// The constructor arguments are name, birthday, and nationality.
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");

ExpressionParser parser = new SpelExpressionParser();

Expression exp = parser.parseExpression("name"); 
String name = (String) exp.getValue(tesla);
// name == "Nikola Tesla"

exp = parser.parseExpression("name == 'Nikola Tesla'");
boolean result = exp.getValue(tesla, Boolean.class);
// result == true

10.2 Bean的属性和方法
     使用注解的方式需要用到@Value,在属性文件的读取中使用的是$,而在spring el中则使用#。

@Component
public class Person {
	@Value("#{100}")
	private Long id;
	@Value("#{'jorge'}")
	private String name;
        //setters and getters
}

@Component
public class ELBean {
	@Value("#{person.id}")
	private Long id;
	@Value("#{'peppa'}")
	private String name;
	
	@Value("#{person}")
	private Person person;
//setters and getters
}


10.3 使用类的静态常量和方法,运算
@Value("#{T(Math).PI}")
private double pi;
	
@Value("#{T(Math).random() * 100}")
private int random;

@Value("#{person.getName()?.toString()}")
private String note;

@Value("#{person.getName()?:'peppa'}")
private String defaultnote;
分享到:
评论
1 楼 迷茫的眼 2019-05-30  
很详细,可以当手册用,扫到我不少盲点,如果再有个完整实战就更好了。期待大侠的其他博课

相关推荐

    spring bean XML配置入门

    在本文中,我们将深入探讨Spring框架中的Bean XML配置,这是Spring的核心特性之一,它允许我们定义、管理和装配应用中的对象。我们将围绕以下知识点展开: 1. **Spring框架基础**: Spring是一个开源的Java平台,...

    Spring Bean重复执行两次(实例被构造两次)问题分析

    2. **@Autowired注解的误用**:Spring的自动装配机制可能导致Bean的多次实例化。如果一个BeanA依赖于另一个BeanB,同时BeanB也依赖于BeanA,那么Spring在处理依赖关系时可能会陷入循环引用,导致两个Bean都实例化两...

    spring bean 属性总结

    ### Spring Bean 属性详解 Spring框架是Java平台上的一个开源框架,主要用来简化企业级应用程序的开发。在Spring中,核心概念之一就是Bean,它是一个简单的Java对象,由Spring IoC容器管理。Spring通过XML配置文件...

    简单了解Spring Bean常用注解的装配

    Spring Bean常用注解的装配 Spring Bean是Spring框架中的核心概念,用于管理和装配JavaBean对象。在Spring框架中, Bean的装配可以通过XML配置文件或基于注解的方式进行。在基于注解的方式中,Spring框架定义了一...

    加载jar包中的spring配置文件

    5. **Spring的Bean定义**:配置文件通常包含Bean的定义,这些Bean代表了应用中的对象实例。通过配置文件,我们可以定义Bean的依赖关系、初始化方法、生命周期等。 6. **MyBatis集成**:`spring_mybatis`可能指的是...

    spring装配bean实例代码

    在Spring框架中,Bean装配是核心功能之一,它负责初始化、配置和管理应用程序中的对象。本文将深入探讨Spring装配Bean的实例代码,帮助你更好地理解这一关键概念。 首先,Spring装配Bean主要有两种方式:XML配置和...

    Spring的Bean配置

    在Spring中,Bean是应用中的对象,它们由Spring IoC容器负责创建、管理和装配。Bean配置是定义这些对象如何被创建和如何相互关联的过程。 **IoC(Inversion of Control)和DI(Dependency Injection)**: IoC是...

    spring装配bean的3种方式总结

    Spring装配Bean的3种方式总结 Spring框架是Java EE应用程序的核心框架之一,它提供了依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)等功能。依赖注入是Spring框架的核心...

    day38 16-Spring的Bean的装配:注解的方式

    在Spring框架中,Bean的装配是核心功能之一,它允许我们管理对象的生命周期和依赖关系。本篇将探讨“注解的方式”来实现Spring Bean的装配。注解提供了声明式的方式来配置Bean,使得代码更加简洁,减少了XML配置的...

    spring入门教程之bean的继承与自动装配详解

    本文将深入探讨Spring Bean的继承与自动装配。 首先,让我们了解Bean的基本定义。在Spring配置文件中,`&lt;beans&gt;`元素作为根元素,包含了一系列`&lt;bean&gt;`子元素。每个`&lt;bean&gt;`元素定义了一个Bean实例,它由一个唯一的...

    Web项目中获取SpringBean与在非Spring组件中获取SpringBean.pdf

    总的来说,获取非Spring管理组件中的SpringBean主要有两种方式:一是通过实现`ApplicationContextAware`接口并存储ApplicationContext,二是使用注解和静态内部类来注入BeanFactory。这两种方法都是Spring框架提供的...

    Spring装配bean方法实例总结

    Spring装配bean方法实例总结 Spring框架中,bean的装配是非常重要的一个步骤,它可以通过多种方式来实现,包括XML配置、Java配置和自动装配等。下面是Spring装配bean方法实例总结。 一、XML配置 在Spring框架中...

    Spring之核心容器bean

    在Spring中,bean是一个由容器管理的对象,它的实例化、初始化、装配和销毁都是由Spring容器控制的。你可以通过XML、注解或者Java配置类来定义bean。例如,一个简单的XML配置如下: ```xml &lt;bean id="myBean" class...

    spring中的bean

    在Spring中,Bean通常代表应用程序中的一个对象,这些对象由Spring容器(ApplicationContext)管理,包括创建、初始化、装配和销毁。Bean可以通过XML配置文件、注解或者Java配置类进行定义。 1. **Bean的定义**:在...

    第四章 Spring Bean基础1

    Spring Bean 是 Spring 框架的核心概念,它代表了应用程序中的一个对象,这个对象可以被 Spring 容器管理,包括创建、初始化、装配、销毁等生命周期过程。在 Spring 中,Bean 定义是由 `BeanDefinition` 接口来表示...

    普通类调用Spring bean对象

    2. **@Autowired**:如果普通类也是Spring的一部分,即它也被Spring管理,那么可以使用注解`@Autowired`来自动装配bean。这样,Spring会自动找到类型匹配的bean并注入到属性中。例如: ```java @Service public ...

    粗略实现spring创建bean

    6. Spring Bean 的装配 - 自动装配:通过`@Autowired`注解自动寻找匹配类型的Bean进行装配。 - 配置文件指定:在XML配置文件中使用`&lt;bean&gt;`标签的`ref`属性指定依赖的Bean。 - 使用`@Qualifier`:当有多个相同...

    Spring中关于Bean的管理的课件

    在Spring框架中,Bean的管理是其核心特性之一,它涉及到Bean的创建、初始化、装配以及销毁等整个生命周期过程。本课件主要涵盖了以下几个关键知识点: 1. **控制反转(IoC)和依赖注入(DI)**:Spring的核心设计...

    Java中Spring获取bean方法小结

    Spring的核心在于其BeanFactory和ApplicationContext,它们使得对象的管理和装配变得简单。这里我们将详细探讨如何在Java中通过Spring获取配置的bean。 1. **BeanFactory与ApplicationContext** - **BeanFactory*...

    详解Spring中Bean的生命周期和作用域及实现方式

    Spring中Bean的生命周期和作用域及实现方式 Spring是一个非常流行的Java应用程序框架,它提供了一个灵活的机制来管理Bean的生命周期和作用域。Bean的生命周期和作用域是Spring框架中两个非常重要的概念,它们决定了...

Global site tag (gtag.js) - Google Analytics