项目中使用到的Spring常用注解

Spring常用注解

@ConfigurationProperties(prefix=“dh”)

该注解可以将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;

@ConditionalOnProperty

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
)

@Autowired

该注解可以将在spring容器中声明的bean自动注入到属性中,默认是根据类型注入,但是当该注解应用于List时,如果T是接口,会将该接口T的所有实现类都注入到该List中

例如 A、B、C 都implments D
如果使用@Autowired 注解D 
@Autowired
private List<D> selectors = new ArrayList<>();
所有实现类A,B,C都会集中到selcetors这个集合中。

@ControllerAdvice

+@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/>

@Condition系列注解

条件化地配置bean

@ConditionalOnBean:我们需要某个 Bean 已经存在应用上下文时才会加载

@ConditionalOnMissingBean:我们需要某个 Bean 在应用上下文不存在时才会加载

@ConditionalOnClass
@ConditionalOnMissingClass:判断某个类是否存在于 classpath 中,如果不存在就加载,否则不加载

@ConditionalOnExpression

@Import和@ImportResource

在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

该注解可以从属性文件形成的键值对中提取value并注入到类的属性中。

PropertyPlaceholderConfigurer 负责将属性文件.properties中的数据转换为键值对,并放入到上下文环境ApplicationContext中的Properties中,当需要使用时${key}@Value{"key"},spring会自动从上下文中查找key对应的value,找不到会报错。

@PropertyResource(“classpath:xxx.properties”)

该注解可以将单独将某一属性文件加载到ApplicationContext上下文中,然后使用@Value注解可以将具体的值注入到类的属性中

相当于·PropertyResourcePlaceholderConfigurer·类,
在使用@Bean声明PropertyResourcePlaceholderConfigurer时,必须使用static,这些继承了 BeanFactoryPostProcessorBeanPostProcessor 的类会在容器初始化之前进行初始化,所以必须声明为static

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

spring boot默认从application.properties中读取数据,如果application.properties文件和自定义spring.properties文件中有相同的键值对,则优先获取application.properties文件中的数据。

加载属性文件到上下文的3种方式:

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"/>

@SpringBootTest

作用:在测试中引入ApplicationContext

@AutoConfigureMockMvc

作用:用于自动配置MockMvc

@MockBean

作用:会生成一个模拟的对象来代替真实的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 Aop

1. 切点表达式

1.1 execution

由于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;

1.2 with

within表达式的粒度为类,其参数为全路径的类名(可使用通配符),表示匹配当前表达式的类的所有方法。如下是within表达式的语法:

within(declaring-type-pattern)

1.3 @within

前面我们讲解了within的语义表示匹配指定类型的类实例,这里的@within表示匹配带有指定注解的类,其使用语法如下所示:

@within(annotation-type)

匹配标注了指定注解的类及其所有子类 , 如 @within(org.springframework.stereotype.Service)Horseman加上@Service标注,则Horseman及其子类的所有方法都匹配

1.4@annotation

@annotation的使用方式与@within的相似,表示匹配使用@annotation指定注解标注的方法将会被环绕,其使用语法如下:

@annotation(annotation-type)

例如 @annotation(org.springframework.transaction.annotation.Transactional)表示标注了@Transactional的方法

@With和@Annotation的区别在于:

1.粒度不同,@with中的注解用来匹配指定注解所注解的类,使用level是class;而@annotation中的注解用来匹配注解标记的方法,使用levelmethod;

2.就是说@with针对类,@annotation针对方法

1.5 args

args表达式的作用是匹配指定参数类型和指定参数数量的方法,无论其类路径或者是方法名是什么。这里需要注意的是,args指定的参数必须是全路径的。如下是args表达式的语法:

args(param-pattern)
例如:
args(java.lang.String,..,java.lang.Integer)

1.6 @args

@args表示使用指定注解标注的类作为某个方法的参数时该方法将会被匹配。如下是@args注解的语法:

@args(annotation-type)
       如下示例表示匹配使用了com.spring.annotation.FruitAspect注解标注的类作为参数的方法:

@args(com.spring.annotation.FruitAspect)

1.7 this和target

thistarget需要放在一起进行讲解,主要目的是对其进行区别。

thistarget表达式中都只能指定类或者接口.

target()会匹配指定的类及其子类

thistarget的区别:this是在运行时生成代理类后,才判断代理类与指定的对象类型是否匹配

在面向切面编程规范中,this表示匹配调用当前切点表达式所指代对象方法的对象,target表示匹配切点表达式指定类型的对象。比如有两个类A和B,并且A调用了B的某个方法,如果切点表达式为this(B),那么A的实例将会被匹配,也即其会被使用当前切点表达式的Advice环绕;如果这里切点表达式为target(B),那么B的实例也即被匹配,其将会被使用当前切点表达式的Advice环绕。

1.8 @target()

@target()会匹配所有标注了指定注解的类中的方法

如: @target(org.springframework.stereotype.Service)表示所有标注了@Service的类的所有方法

1.9 @DeclareParents

@DeclareParents也称为Introduction(引入),表示为指定的目标类引入新的属性和方法。关于@DeclareParents的原理其实比较好理解,因为无论是Jdk代理还是Cglib代理,想要引入新的方法,只需要通过一定的方式将新声明的方法织入到代理类中即可,因为代理类都是新生成的类,因而织入过程也比较方便。如下是@DeclareParents的使用语法:

@Aspect
@Component
public AopAspect{
	@DeclareParents(value = "TargetType", defaultImpl = WeaverType.class)
	private WeaverInterface attribute;
}
value表示目标类(需要引入新方法的类)
defaultImpl表示新方法所在的类

引入的示意图

你可能感兴趣的:(spring)