该注解可以将properties属性文件中的信息,读取并封装成一个实体类。但也仅仅是将属性文件的数据封装到实体中,并没有将该实体注册为bean,若想在spring上下文中使用,则需要在实体类上使用注解@Component,或者在配置类中使用注解@EnableConfigurationProperties(“指定的实体类”)
#dh.properties
dh.clientCurveType=1
dh.clientUseAlgorithm=AES128/CBC/PKCS5Padding
dh.useSecondAsExpireTimeServerList=das,rms,sac
@ConfigurationProperties(
prefix = "dh"
)
public class DhProperties {
private String clientCurveType;
private String clientUseAlgorithm;
private List<String> useSecondAsExpireTimeServerList = new LinkedList();
private List<String> timeOutErrorCodeList = new LinkedList();
private String sessionExpiredCode;
Spring Boot通过@ConditionalOnProperty
来控制TraceAutoConfiguration
是否生效
@Configuration
@ConditionalOnClass(Sender.class)
@EnableConfigurationProperties(TraceProperties.class)
@ConditionalOnProperty(prefix = "trace", value = "enable", matchIfMissing = true)
public class TraceAutoConfiguration implements DisposableBean, WebMvcConfigurer {
...
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
String[] value() default {}; //数组,获取对应property名称的值,与name不可同时使用
String prefix() default "";//property名称的前缀,可有可无
String[] name() default {};//数组,property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用
String havingValue() default "";//可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置
boolean matchIfMissing() default false;//缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错
boolean relaxedNames() default true;//是否可以松散匹配,至今不知道怎么使用的
}
}
例如:一般@ConditionalOnProperty
和@ConfigurationProperties
和@Configuration
配合使用,用在XXXAutoConfigutation
自动配置类上。
@Configuration
@EnableConfigurationProperties({DhProperties.class})
@ConditionalOnProperty(
prefix = "dh",
value = {"enable"},
matchIfMissing = true
)
该注解可以将在spring容器中声明的bean自动注入到属性中,默认是根据类型注入,但是当该注解应用于List时,如果T是接口,会将该接口T的所有实现类都注入到该List中
例如 A、B、C 都implments D
如果使用@Autowired 注解D
@Autowired
private List<D> selectors = new ArrayList<>();
所有实现类A,B,C都会集中到selcetors这个集合中。
+@ResponseBody
= @RestControllerAdvice
control层的全局异常处理
@ControllerAdvice
public class GlobalExceptionResolver{
@ResponseBody
@ExceptionHandler({Exception.class})
public Object requestException(HttpServletRequest request, Exception exception) {
DefaultMessage defaultMessage = DefaultMessageHolder.getDefaultMessage();
ErrorCodeEnum errorCodeEnum = ErrorCodeEnum.FAILED;
String messageKey = "";
if (defaultMessage != null) {
errorCodeEnum = defaultMessage.errorCodeEnum();
messageKey = defaultMessage.messageKey();
}
if (isUiRequest(request)) {
UiVo<Object> uiVo = UiVoUtil.generateResultFromException(exception, errorCodeEnum, messageKey);
LogUtils.logError(uiVo.getCode(),uiVo.getMsg(), exception);
return uiVo;
} else {
ApiVo<Object> apiVo = ApiVoUtil.generateApiResultData(exception, errorCodeEnum, messageKey);
LogUtils.logError(apiVo.getCode(),apiVo.getMsg() , exception);
return apiVo;
}
}
}
会将exception中的code,massagekey封装到UiVo或者ApiVo中
开启各种注解的使用开关,例如 @AutoWired @Resource 、@PostConstruct、@PreDestroy
<context:annotation-config/>
也就是说,你不用xml中显示配置,需要的时候尽管用@Resource或者@Autowired来自动注入!
所以配置
就不需要配置
<context:component-scan>,该注解可以扫描并注册你使用注解诸如@controller @service @component..的bean!!!
<tx:annotation-driven/>
<aop:aspectj-autoproxy proxy-target-class="true" />
<mvc:annotation-driven/>
条件化地配置bean
@ConditionalOnBean:我们需要某个 Bean 已经存在应用上下文时才会加载
@ConditionalOnMissingBean:我们需要某个 Bean 在应用上下文不存在时才会加载
@ConditionalOnClass
@ConditionalOnMissingClass:判断某个类是否存在于 classpath 中,如果不存在就加载,否则不加载
@ConditionalOnExpression
在JavaConfig配置中引用XML配置,使用@ImportResource注解。例如:
@Configuration
引入xml配置
@ImportResource(locations = {"classpath:springbeans/spring-beans.xml"})
引入JavaConfig配置
@Import(xxx.class)
public class VmsBeanDefinneConfig {
}
在XML配置中引用JavaConfig和其他xml配置
引入JavaConfig
<bean id="traceAutoConfiguration" class="com.hikvision.cms.ontrain.trace.TraceAutoConfiguration"/>
引入xml配置
<import resource="classpath:context-ontrain-service.xml"/>
引入JavaConfig,即把配置类TraceAutoConfiguration在XML中声明为bean
@Configuration
public class TraceAutoConfiguration
implements DisposableBean, WebMvcConfigurer {}
该注解可以从属性文件形成的键值对中提取value并注入到类的属性中。
PropertyPlaceholderConfigurer
负责将属性文件.properties
中的数据转换为键值对,并放入到上下文环境ApplicationContext
中的Properties
中,当需要使用时${key}
和@Value{"key"}
,spring会自动从上下文中查找key对应的value,找不到会报错。
该注解可以将单独将某一属性文件加载到ApplicationContext
上下文中,然后使用@Value
注解可以将具体的值注入到类的属性中
相当于·PropertyResourcePlaceholderConfigurer·类,
在使用@Bean
声明PropertyResourcePlaceholderConfigurer
时,必须使用static
,这些继承了 BeanFactoryPostProcessor
和 BeanPostProcessor
的类会在容器初始化之前进行初始化,所以必须声明为static
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
spring boot默认从application.properties
中读取数据,如果application.properties
文件和自定义spring.properties
文件中有相同的键值对,则优先获取application.properties
文件中的数据。
1.使用@PropertyResource("classpath:xxx.properties")
2.使用@Bean
注解声明PropertyResourcePlaceholderConfigurer
,可以使用
.setLocation()
方法来设置属性文件所在位置
propertyResourceConfigurer.setLocation(new ClassPathResource("spring.properties"));
如果不
设置Location
,会默认去application.properties
文件中查找数据。
3.使用xml
配置PropertyResourcePlaceholderConfigurer
<property name="location" value="classpath:application.properties"/>
bean>
application.propertie
属性文件无论是否显式加载,都会在声明PropertyResourcePlaceholderConfigurer
时自动加载到上下文中。
4.使用
这个注解只能使用一次,多次使用,除第一个外的
都会被spring忽略
<context:property-placeholder location="classpath:spring.properties"/>
作用:在测试中引入ApplicationContext
作用:用于自动配置MockMvc
作用:会生成一个模拟的对象来代替真实的bean, 模拟底层数据的返回,而不是调用原本真正的实现
在SpringBoot 中, @MockBean
会将mock的bean
替换掉 SpringBoot 管理的原生bean
,从而达到mock
的效果 。
spring的事件监听器有两种实现方式:
1.通过实现ApplicationListener
接口
@Service
public class MyListenser implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent applicationEvent) {
System.out.println(
"这是自定义的监听器,容器启动或刷新时打印的"
);
}
}
2.通过@EventListener注解实现
@EventListener是用来注解方法的
@Service
public class MyAnnotationListener {
@EventListener
public void handleApplicationEvent(ContextRefreshedEvent applicationEvent){
System.out.println(
"这是通过@EventListener注解实现的监听器"
);
}
}
默认情况下,使用@EventListener
注解的监听器会先于实现ApplicationListener
的监听器启动。
可以使用@Order注解改变监听器的先后启动顺序。
@Order(1),@Order(5),其中整数值越小,优先级越高
@Valid
和校验约束(@Max,Size)
等配合使用,可以实现对前端传来参数的校验
由于Spring切面粒度
最小是达到方法级别
,而execution
表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP
的业务场景也只需要达到方法级别即可,因而execution表达式
的使用是最为广泛的。如下是execution表达式的语法:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
modifiers-pattern
:方法的可见性,如public,protected;ret-type-pattern
:方法的返回值类型,如int,void等;declaring-type-pattern
:方法所在类的全路径名,如com.spring.Aspect;name-pattern
:方法名类型,如buisinessService();param-pattern
:方法的参数类型,如java.lang.String;throws-pattern
:方法抛出的异常类型,如java.lang.Exception;within
表达式的粒度为类,其参数为全路径的类名(可使用通配符),表示匹配当前表达式的类的所有方法。如下是within表达式的语法:
within(declaring-type-pattern)
前面我们讲解了within
的语义表示匹配指定类型的类实例,这里的@within表示匹配带有指定注解的类,其使用语法如下所示:
@within(annotation-type)
匹配标注了指定注解的类及其所有子类 , 如 @within(org.springframework.stereotype.Service)
给Horseman
加上@Service标注,则Horseman
及其子类
的所有方法都匹配
@annotation
的使用方式与@within
的相似,表示匹配使用@annotation
指定注解标注的方法将会被环绕,其使用语法如下:
@annotation(annotation-type)
例如 @annotation(org.springframework.transaction.annotation.Transactional)
表示标注了@Transactional
的方法
1.粒度不同,@with
中的注解用来匹配指定注解所注解的类,使用level
是class;而@annotation
中的注解用来匹配注解标记的方法,使用level
是method
;
2.就是说@with
针对类,@annotation
针对方法
args
表达式的作用是匹配指定参数类型和指定参数数量的方法
,无论其类路径或者是方法名是什么。这里需要注意的是,args指定的参数必须是全路径的。如下是args表达式的语法:
args(param-pattern)
例如:
args(java.lang.String,..,java.lang.Integer)
@args
表示使用指定注解标注的类作为某个方法的参数时该方法将会被匹配。如下是@args注解
的语法:
@args(annotation-type)
如下示例表示匹配使用了com.spring.annotation.FruitAspect注解标注的类作为参数的方法:
@args(com.spring.annotation.FruitAspect)
this
和target
需要放在一起进行讲解,主要目的是对其进行区别。
this
和target
表达式中都只能指定类或者接口.
target()
会匹配指定的类及其子类
this
和target
的区别:this
是在运行时生成代理类后,才判断代理类与指定的对象类型是否匹配
在面向切面编程规范中,this
表示匹配调用当前切点表达式所指代对象方法的对象,target
表示匹配切点表达式指定类型的对象。比如有两个类A和B,并且A调用了B的某个方法,如果切点表达式为this(B),那么A的实例将会被匹配,也即其会被使用当前切点表达式的Advice环绕;如果这里切点表达式为target(B),那么B的实例也即被匹配,其将会被使用当前切点表达式的Advice环绕。
@target()
会匹配所有标注了指定注解的类中的方法
如: @target(org.springframework.stereotype.Service)
表示所有标注了@Service
的类的所有方法
@DeclareParents
也称为Introduction
(引入),表示为指定的目标类
引入新的属性和方法。关于@DeclareParents
的原理其实比较好理解,因为无论是Jdk代理还是Cglib代理,想要引入新的方法,只需要通过一定的方式将新声明的方法织入到代理类中即可,因为代理类都是新生成的类,因而织入过程也比较方便。如下是@DeclareParents
的使用语法:
@Aspect
@Component
public AopAspect{
@DeclareParents(value = "TargetType", defaultImpl = WeaverType.class)
private WeaverInterface attribute;
}
value表示目标类(需要引入新方法的类)
defaultImpl表示新方法所在的类