spring 高级装配


一、环境与profile

1、java配置profile

public interface DateSourceInterFace {//下面两个实现的接口
    public void printInfo();
}
@Component
@Profile("dev")
public class DevDateSour implements DateSourceInterFace{
    @Override
    public void printInfo() {
        System.out.println("this DEV profile.......");
    }
}
@Component
@Profile("pro")
public class ProDateSour implements DateSourceInterFace{
    @Override
    public void printInfo() {
        System.out.println("this Pro profile.......");
    }
}
@ComponentScan//spring扫描到spring容器中创建bean对象
@Configuration
public class ProfileConfig {

}

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ProfileConfig.class)
@ActiveProfiles("pro")//当前激活pro环境
public class ProfileTest {
    @Autowired
    private DateSourceInterFace dateSource;
    
    @Test
    public void test01(){
      dateSource.printInfo();
    }
}

结果:

this Pro profile.......

2、xml中配置profile

一个xml对象相当于一个配置类;如下有两种方式一种是分别两个xml表示两个环境,第二种是一个xml里面配置两个并设置profile属性,如下就是第二种演示。

<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">
    <!-- 方式一 -->
    <!-- profile="dev">-->

    <!-- 方式二 -->
    <beans profile="dev">
        <bean id="dateSour" class="part03.DevDateSour"/>
    </beans>
    <beans profile="pro">
        <bean id="dateSour" class="part03.ProDateSour"/>
    </beans>
</beans>

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/profileContext.xml"})
@ActiveProfiles("pro")
public class ProfileXmlTest {
    @Autowired
    private DateSourceInterFace dateSource;

    @Test
    public void test01(){
        dateSource.printInfo();
    }
}

二、激活profile

1、激活方式有如下几种:

1、作为DispatcherServlet的初始化参数
2、作为web应用的上下文参数
3、作为环境变量
4、使用@ActiveProfiles激活

下面是web.xml中配置

<!-- 方式一、为上下文设置默认profile -->
<context-param>
    <param-name>spring.profiles.default</param-name>
    <param-value>dev</param-value>
</context-param>

<!-- 二、为servlet设置激活的profile -->
<servlet>
  <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>spring.profiles.active</param-name>
        <param-value>pro</param-value>
    </init-param>
</servlet>

<!-- 方式三、不是web.xml中,直接运行war包时配置环境参数 -->
-Dspring.profiles.active="pro"

2、读取方式和顺序

①如果同时设置了 spring.profile.active=dev 和 spring.profile.default=pro ,只激活dev配置。
②如果没有配置spring.profile.active,只配置了spring.profile.default,才会读取default配置。
③那些没有定义在profile中的bean,任何时候都创建。

三、条件化bean @Condition注解

1、@Condition注解的作用

@Condition注解的bean,只有满足实现 Condition 接口的 matches 方法才创建,否则忽略。

@Configuration
public class MagicConfig {
  @Bean
  //MagicExistsCondition类中match方法返回true就穿件如下bean
  @Conditional(MagicExistsCondition.class)
  public MagicBean magicBean() {
    return new MagicBean();
  }  
}
public class MagicExistsCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment env = context.getEnvironment();
    return env.containsProperty("magic");
  }  
}

2、Condition 接口使用

Condition 接口的matches方法的两个参数

public interface ConditionContext {
//可以检查bean定义
    BeanDefinitionRegistry getRegistry();
//检查bean是否存在,检查bean属性    
    ConfigurableListableBeanFactory getBeanFactory();
//获取环境中存在或者值时多少    
    Environment getEnvironment();
//获取resourceLoader加载的资源 
    ResourceLoader getResourceLoader();
//返回累加器,并检查类是否存在       
    ClassLoader getClassLoader();
}

AnnotatedTypeMetadata 可以检查@bean注解的方法上的其他注解信息。

public interface AnnotatedTypeMetadata {
//
	boolean isAnnotated(String annotationName);
	Map<String, Object> getAnnotationAttributes(String annotationName);
	Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);
	MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);
	MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
}

3、@Profile注解源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
	/**
	 * The set of profiles for which the annotated component should be registered.
	 */
	String[] value();
}
class ProfileCondition implements Condition {

	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		if (context.getEnvironment() != null) {
	//获取@Profile注解的属性value值
			MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
			if (attrs != null) {
				for (Object value : attrs.get("value")) {
				//从环境中检查是否含有该vlaue值,有则激活该环境,并创建该bean对象
					if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
						return true;
					}
				}
				return false;
			}
		}
		return true;
	}
}

四、运行时值注入

1、属性占位符 ${…}

①传统xml脚本配置

public class Food {
    private String eatFood;
    public void setEatFood(String eatFood) {
        this.eatFood = eatFood;
    }
    public String getEatFood() {
        return eatFood;
    }
    @Override
    public String toString() {
        return "Food{" + "eatFood='" + eatFood + '\'' +'}';
    }
}
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean id="food" class="part03.Food">
        <!--运行时动态从文件中读取值-->
        <property name="eatFood" value="${food.eatFood}"/>
    </bean>

    <!--读取配置属性文件 或者 创建PropertySourcesPlaceholderConfigurer读取-->
    <context:property-placeholder location="classpath:/part03/runTime.properties"/>
</beans>

classpath:/part03/runTime.properties配置属性文件

food.eatFood=午餐必须带饭

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
//读取xml配置类
@ContextConfiguration(locations = {"classpath:/part03/runTimeConfig.xml"})
public class RuntTimeTest {
    @Autowired
    private Food food;

    @Test
    public void test01(){
        System.out.println(food.toString());
    }    
}

结果: Food{eatFood=‘午餐必须带饭’}

②java注解实现 @PropertySource

如上相同的properties文件,不使用xml,直接Food类绑定属性

@Component
@PropertySource(value = {"part03/runTime.properties"})
public class Food {
    @Value("${food.eatFood}")
    private String eatFood;

    public String getEatFood() {
        return eatFood;
    }

    public void setEatFood(String eatFood) {
        this.eatFood = eatFood;
    }

    @Override
    public String toString() {
        return "Food{" + "eatFood='" + eatFood + '\'' + '}';
    }
}

③ 或者配合自动装配和组件扫描,配合@Value注解

@ContextConfiguration(locations = {“classpath:/part03/runTimeConfig.xml”})配合xml配置文件,直接可以读取值到容器中,并使用@Value设置进去
@Value 和 @Autowired 相似用法,创建bean时自动注入值

public class Food {
    @Value("${food.eatFood}")
    private String eatFood;

    public String getEatFood() {
        return eatFood;
    }

    public void setEatFood(String eatFood) {
        this.eatFood = eatFood;
    }

    @Override
    public String toString() {
        return "Food{" + "eatFood='" + eatFood + '\'' + '}';
    }
}

part03/runTimeConfig.xml

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean id="food" class="part03.Food"/>

    <!--读取配置属性文件-->
    <context:property-placeholder location="classpath:/part03/runTime.properties"/>
</beans>

测试:

@RunWith(SpringJUnit4ClassRunner.class)
//读取xml配置类
@ContextConfiguration(locations = {"classpath:/part03/runTimeConfig.xml"})
public class RuntTimeTest {
      @Autowired
    private Food food;

    @Test
    public void test02(){
        System.out.println(food.toString());
    }
}

@PropertySource配置的用法

2、spring表达式语言 #{…}

①bean对象的id引用,可以获取对应的属性和方法

②表达式中使用类型

③运算符

④正则表达式

public class Eating {
    //引用bean
    @Value("#{food}")
    private Food food;
    //引用bean的属性,但是该属性必须要有get方式的方法才行
    @Value("#{food.eatFood}")
    private String eatFood;
    //引用bean的方法,?是food不为空才执行方法
    @Value("#{food?.toString()}")
    private String eatFoods;
    //使用T表示类型,可调用静态方法或常量
    @Value("#{T(System).currentTimeMillis()}")
    private Long currentTime;
    //使用T表示类型,可调用静态方法或常量
    @Value("#{T(Math).PI * 2}")
    private Long PiValue;
    //正则表达式匹配
    @Value("#{food.eatFood matches '.*'}")
    private boolean relax;

    public void myFood(){
        System.out.println(food.toString());
        System.out.println(eatFood);
        System.out.println(eatFoods);
        System.out.println(currentTime);
        System.out.println(PiValue);
        System.out.println(relax);
    }
}

结果:

Food{eatFood='午餐必须带饭'}
午餐必须带饭
Food{eatFood='午餐必须带饭'}
1658414010364
6
true

总结

一个xml配置文件相当于一个配置类

java配置类可以和xml配置一起混合使用,互相引用,注入属性。

@PropertySource 注解可以直接使用@Value读取容器中的属性值

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值