Spring高级装配

一、Spring profile

使用spring profile可以根据环境创建bean

1. 配置

java配置

@Profile("dev")
Spring3.1只能使用在类级别上,Spring 3.2开始可以使用在方法级别上,与@bean一同使用。

xml配置
<beans profile="dev">
  ...
</beans>

2. 激活

Spring在确定那个profile处于激活状态时,需要依赖两个独立属性,spring.profiles.activespring.profiles.default。设置了spring.profiles.active属性,激活该属性值,否则激活spring.profiles.default,都没有设置则都不会激活。
激活方式:

  • 作为DispatherServlet的初始化参数
  • 作为Web应用的上下文参数
  • 作为JNDI条目
  • 作为环境变量
  • 作为JVM的系统属性
  • 在集成测试类上,使用@ActiveProfiles注解
    Example:
    web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring/spring.xml</param-value>
	</context-param>
	<!-- 为上下文设置的默认的profile -->
	<context-param>
		<param-name>spring.profiles.default</param-name>
		<param-value>dev</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

	<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>location</param-value>
		</init-param>
		<!-- 为Servlet设置的默认的profile -->
		<init-param>
			<param-name>spring.profiles.default</param-name>
			<param-value>dev</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</servlet>
</web-app>

Test.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { RootConfig.class })
@ActiveProfiles("dev")
public class UserTest {}

二、条件化的bean

在满足特定需求的情况下才创建bean

@Conditional(Class.class)注解标注的bean
Class类可以是任意实现了Condition接口的类型 。

三、处理自动装配的歧义性

1. 设置首选的bean,只适用于一个首选bean

@Primary

	<bean id="" class="" primary="true">

2. 限定自动装配的bean

@Qualifier("限定符")
@Autowired , @Inject协同使用,在注入的时候指定要注入哪个bean。

  • 限定符可以是最简单的bean id,为了防止重构代码,改变类名,默认的bean id发生改变,可以自定义限定符
  • 创建自定义的限定符:在bean声明上添加@Qualifier("")注解
  • 使用自定义限定符注解

四、 bean的作用域

默认情况下,Spring应用上下文中的所有bean都是以单例形式创建的。
Spring定义的多种作用域,可以基于这些作用域创建bean:

  • 单例 (Singleton)
  • 原型 (Prototype) : 每次注入或者通过spring应用上下文获取的时候都会创建一个新的实例。
  • 会话(Session):在Web应用中,每个会话创建一个实例。
  • 请求(Request):在Web应用中,每个请求创建一个实例。

改变默认作用域使用@Scope注解,可以与 @Component 或者 @Bean一起使用。

使用会话和请求作用域

注解方式:
会话作用域的bean注入到单例作用域,由于会话作用域在用户进入系统时才会创建,而单例是在应用上下文加载的时候创建,而且会话作用域需要是特定用户的实例注入。Spring会将一个代理注入,使用@ScopeproxyMode属性设置代理模式,如果是接口@Scope( value = WebApplicationContext.SCOPE_SESSION proxyMode=ScopedProxyMode.INTERFACES),如果是类,需要使用CGLib生成基于类的代理proxyMode=ScopedProxyMode.TARGET_CLASS。请求作用域同样以代理方式注入。
XML配置
使用xml配置声明会话或者请求作用域的bean,使用<bean>元素的scope属性只能设置bean的作用域,设置代理模式需要使用Spring aop 命名空间的一个新元素<aop:scoped-proxy />

<bean id="" class="" scope="session">
	<aop:scoped-proxy />
</bean>

默认使用CGLib创建目标类的代理,设置<aop:scoped-proxy proxy-target-class="fasle" />,使其生成基于接口i的代理。

五、运行时值注入

Spring提供了两种在运行时求值的方式:

  • 属性占位符(Property palceholder)
  • Spring表达式语言(SpEL)

1、注入外部值

Spring中的Environment
通过@PropertySource(value = { "classpath:/properties/db.properties" }),这个属性文件会加载到Spring的Environment中,可以从这里检索属性,例如:

@PropertySource(value = { "classpath:/properties/db.properties" })
public class Test {
 @Autowired
 private Environment env;
 
 public void envTest() {
      String url = env.getProperty("jdbc.url");
      System.out.println(url);
    }
}

其他的一些方法:

String[] getActiveProfiles();
String[] getDefaultProfiles();
boolean containsProperty(String key);
··· ···

解析属性占位符
xml : ${jdbc.driver}
java:@Value("${jdbc.driver}")
使用占位符需要配置属性源,可以通过配置PropertySourcesPlaceholderConfigurer

    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        return placeholderConfigurer;
    }

xml配置:

<context:property-placeholder/>

解析外部属性能将值的处理推迟到运行时,但是只能根据名称解析属性源的属性。

2、使用Spring表达式语言进行装配

SpEL可以将在运行时计算得到的值装配到bean,SpEL有很多特性,包括:

  • 使用bean的id引用bean
  • 调用方法和访问对象的属性
  • 对值进行算术、关系和逻辑运算
  • 正则表达式匹配
  • 集合操作

SpEL还能用于依赖注入以外的其他地方。

SpELl样例:
SpEL需要放到#{···}

#{1}
//T() 表达式会将System视为Java中对应的类型,调用其静态方法
#{T(System).currentTimeMillis()}
//引用其他bean或bean的属性
#{beanId.beanProperty}
//通过systemProperties对象引用系统属性
#{systemProperties['jdbc.url']}
//SpEL运算符
#{2 * T(java.lang.Math).PI * circle.radius}
//集合计算
#{musicBox.songs[4].title}
#{'This is a test'[3]}
··· ···
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值