7.高级装配(一)
1. 环境与Profile
1.解决不同环境不同配置
- maven构建时,使用profiles来确定将哪一个配置编译到可部署的应用
- 缺点:不同环境重新构建,可能引入bug
- 使用Spring profile
2.配置方式
-
Java
-
可以放在类上和方法上,类上的级别会覆盖方法上的,放在类级别上,表示该类型所有的bean都受此影响
package com.desmond.springlearning.profiles; import com.desmond.springlearning.profiles.vo.Person; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; /** * Created by presleyli on 2018/4/6. */ @Configuration @Profile("dev") public class ConfigurationConfig { @Bean @Profile("prod") public Person getProdPerson() { Person person = new Person(); person.setName("prod"); return person; } @Bean public String name() { return "prod"; } @Bean @Profile("test") public Person getTestPerson() { Person person = new Person(); person.setName("test"); return person; } @Bean @Profile("dev") public Person getDevPerson() { Person person = new Person(); person.setName("dev"); return person; } }
-
JVM配置 参数
-Dspring.profiles.default=dev
-
-
XML
-
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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <beans profile="prod"> <bean id="person" class="com.desmond.springlearning.profiles.vo.Person"> <constructor-arg value="prod" /> </bean> </beans> <beans profile="test"> <bean id="testPerson" class="com.desmond.springlearning.profiles.vo.Person"> <constructor-arg value="test"/> </bean> </beans> <beans profile="dev"> <bean id="devPerson" class="com.desmond.springlearning.profiles.vo.Person"> <constructor-arg value="dev"/> </bean> </beans> </beans>
-
JVM配置 参数
-Dspring.profiles.default=dev
-
测试类
package com.desmond.springlearning.profiles; import com.desmond.springlearning.profiles.vo.Person; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author presleyli * @date 2018/10/9 下午10:15 */ public class XmlTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("profiles/config.xml"); Person person = context.getBean(Person.class); System.out.println(person.getName()); } }
-
-
激活 profile
- 须依赖两个属性 spring.profiles.active和 spring.profiles.default, 如果设置了active, 先用active;否使用default. 如果两者均未设置,则无激活的profile, 也就只加载哪些没有定义在profile里的bean.
- 多种方式设置这两个属性
- DispatcherServlet 初始化参数
- Web应用上下文
- JNDI
- 环境变量
- JVM 变量 eg. -Dspring.profiles.default=dev
- 在集成测试类上,使用注解 @ActiveProfiles
-
2. 条件化bean
1. 概念
当一个或者多个bean需要遇到特定条件才创建
2. 举例
-
假设当Person类,当环境中设置人名为Tom时,才认为此人标签为牛掰
-
首先,定义一个条件类,实现Condition接口
package com.desmond.springlearning.conditional; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; /** * @author presleyli * @date 2018/10/9 下午10:55 */ public class PersonCondition implements Condition{ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { String name = conditionContext.getEnvironment().getProperty("name"); return "Tom".equalsIgnoreCase(name); } }
- 定义configuration
package com.desmond.springlearning.conditional; /** * @author presleyli * @date 2018/10/9 下午10:53 */ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class ConConfiguration { @Bean @Conditional(PersonCondition.class) public Person person() { Person person = new Person(); person.setNotes("此人牛掰."); return person; } }
-
Person
package com.desmond.springlearning.conditional; import lombok.Data; /** * @author presleyli * @date 2018/10/9 下午10:52 */ @Data public class Person { public String notes; }
-
测试
package com.desmond.springlearning.conditional; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @author presleyli * @date 2018/10/9 下午10:15 */ public class AnnoCondTest { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(ConConfiguration.class); Person person = context.getBean(Person.class); System.out.println(person.getNotes()); } }
-
添加环境变量
name=Tom
-
结果
此人牛掰.
否则找不到bean:Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.desmond.springlearning.conditional.Person' available
-
从4.0 @Profile也使用此法:
-
注解
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.context.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional({ProfileCondition.class}) // 条件 public @interface Profile { String[] value(); }
-
condition
/* * Copyright 2002-2013 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 org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.util.MultiValueMap; /** * {@link Condition} that matches based on the value of a {@link Profile @Profile} * annotation. * * @author Chris Beams * @author Phillip Webb * @author Juergen Hoeller * @since 4.0 */ class ProfileCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { if (context.getEnvironment() != null) { MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs != null) { for (Object value : attrs.get("value")) { if (context.getEnvironment().acceptsProfiles(((String[]) value))) { return true; } } return false; } } return true; } }
-