Spring 常用的注解

264 阅读5分钟

Spring 常用注解

Spring Core Annotations

DI-Related Annotations

  1. @Autowried

    可以用于构造函数、setter 方法、属性注入。

    @Autowried 有一个 boolean 类型的参数required,默认值为 true。当没有找到合适的 bean 注入时,若是 true,则抛出异常,否则,不注入。

    注意:如果用在构造函数上,则构造函数所有的参数都是必需的。

    构造函数注入

    class Car {
        Engine engine;
     
        @Autowired
        Car(Engine engine) {
            this.engine = engine;
        }
    }
    

    setter 方法注入

    class Car {
        Engine engine;
     
        @Autowired
        void setEngine(Engine engine) {
            this.engine = engine;
        }
    }
    

    属性注入

    class Car {
        @Autowired
        Engine engine;
    }
    
  2. @Bean

    标记一个工厂方法。

    @Bean
    Engine engine() {
        return new Engine();
    }
    

    返回的bean 与工厂方法名相同,如果想设置不同的名字,可以使用带有参数的注解,参数的值就是返回 bean 的别名。

    @Bean("engine")
    Engine getEngine() {
        return new Engine();
    }
    

    注意:所有使用@Bean 注解的方法必须在使用@Configuration 注解的类中。

  3. @Qualifier

    与@Autowired 注解一起使用,消除注入的歧义性,可以使用 bean id 或者 bean name。

    如下,两个 bean 实现同一个接口。

    class Bike implements Vehicle {}
     
    class Car implements Vehicle {}
    

    如果 Spring 需要注入一个 Vehicle bean,将发现有多个 Vehicle 类型的 bean,我们可以使用@Qualifier 提供明确的类名。

    构造函数注入

    @Autowired
    Biker(@Qualifier("bike") Vehicle vehicle) {
        this.vehicle = vehicle;
    }
    

    setter 方法注入

    @Autowired
    @Qualifier("bike")
    void setVehicle(Vehicle vehicle) {
        this.vehicle = vehicle;
    }
    

    属性注入

    @Autowired
    @Qualifier("bike")
    Vehicle vehicle;
    
  4. @Required

    用于标记我们想通过 xml注入的 setter 方法

    @Required
    void setColor(String color) {
        this.color = color;
    }
    
    <bean class="com.baeldung.annotations.Bike">
        <property name="color" value="green" />
    </bean>
    
  5. @Value

    注入属性值,可以用于构造函数、setter 方法和属性。

    构造函数

    Engine(@Value("8") int cylinderCount) {
        this.cylinderCount = cylinderCount;
    }
    

    setter方法

    @Autowired
    void setCylinderCount(@Value("8") int cylinderCount) {
        this.cylinderCount = cylinderCount;
    }
    
    @Value("8")
    void setCylinderCount(int cylinderCount) {
        this.cylinderCount = cylinderCount;
    }
    

    属性注入

    @Value("8")
    int cylinderCount;
    
  6. @DependsOn

    Spring 在初始化这个 bean之前初始化其他 beans。一般的,这种依赖注入关系是自动的。

    当存在隐式依赖关系时才需要这个注解,例如,JDBC 驱动或者 static 变量初始化。

    @DependsOn("engine")
    class Car implements Vehicle {}
    
    @Bean
    @DependsOn("fuel")
    Engine engine() {
        return new Engine();
    }
    
  7. @Lazy

    懒加载

    可以使用在

    • @Bean 延迟工厂方法调用
    • @Configuration 所有包含@Bean 注解的方法都将受影响
    • @Component 延迟初始化
    • @Autowired 注解的构造函数、setter 方法或者属性,延迟加载依赖
  8. @Lookup

    返回方法返回类型的实例

    创建一个 prototype bean

    @Component
    @Scope("prototype")
    public class SchoolNotification {
        // ... prototype-scoped state
    }
    

    创建一个单例

    @Component
    public class StudentServices {
     
        // ... member variables, etc.
     
        @Lookup
        public SchoolNotification getNotification() {
            return null;
        }
     
        // ... getters and setters
    }
    
    @Test
    public void whenLookupMethodCalled_thenNewInstanceReturned() {
        // ... initialize context
        StudentServices first = this.context.getBean(StudentServices.class);
        StudentServices second = this.context.getBean(StudentServices.class);
            
        assertEquals(first, second); 
        assertNotEquals(first.getNotification(), second.getNotification()); 
    }
    
  9. @Primary

    @Component
    @Primary
    class Car implements Vehicle {}
     
    @Component
    class Bike implements Vehicle {}
     
    @Component
    class Driver {
        @Autowired
        Vehicle vehicle;
    }
     
    @Component
    class Biker {
        @Autowired
        @Qualifier("bike")
        Vehicle vehicle;
    }
    

    Driver 类,spring 注入一个 Car bean,Biker 类,spring 注入一个 Bike 对象。

  10. @Scope

    @Scope 定义@Component 或者@Bean 定义的 bean 的范围,主要有:singleton、prototype、request、session、globalSession 或者其他自定 scope。

    @Component
    @Scope("prototype")
    class Engine {}
    

Context Configuration Annotations

  1. @Profile

    用于@Component 或者@Bean

    @Component
    @Profile("sportDay")
    class Bike implements Vehicle {}
    
  2. @Import

    不需要组件扫描,可以使用特定的@Configuration 类。

    @Import(VehiclePartSupplier.class)
    class VehicleFactoryConfig {}
    
  3. @ImportResource

    导入 XML 配置

    @Configuration
    @ImportResource("classpath:/annotations.xml")
    class VehicleFactoryConfig {}
    
  4. @PropertySource

    属性文件

    @Configuration
    @PropertySource("classpath:/annotations.properties")
    class VehicleFactoryConfig {}
    
    @Configuration
    @PropertySource("classpath:/annotations.properties")
    @PropertySource("classpath:/vehicle-factory.properties")
    class VehicleFactoryConfig {}
    
  5. @PropertySources

    @Configuration
    @PropertySources({ 
        @PropertySource("classpath:/annotations.properties"),
        @PropertySource("classpath:/vehicle-factory.properties")
    })
    class VehicleFactoryConfig {}
    

Spring Web Annotations

  1. @RequestMapping

    使用在@Controller 注解的类中,标记 request 处理方法,可以使用以下配置:

    path, or its aliases, name, and value: which URL the method is mapped to method: compatible HTTP methods params: filters requests based on presence, absence, or value of HTTP parameters headers: filters requests based on presence, absence, or value of HTTP headers consumes: which media types the method can consume in the HTTP request body produces: which media types the method can produce in the HTTP response body

    @Controller
    class VehicleController {
     
        @RequestMapping(value = "/vehicles/home", method = RequestMethod.GET)
        String home() {
            return "home";
        }
    }
    
    @Controller
    @RequestMapping(value = "/vehicles", method = RequestMethod.GET)
    class VehicleController {
     
        @RequestMapping("/home")
        String home() {
            return "home";
        }
    }
    

    @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping都是由@RequestMapping 转变而来的。

  2. @RequestBody

    自动封装客户端传递过来的 json 格式参数到 bean 中

    @PostMapping("/save")
    void saveVehicle(@RequestBody Vehicle vehicle) {
        // ...
    }
    
  3. @PathVariable

    @RequestMapping("/{id}")
    Vehicle getVehicle(@PathVariable(required = false) long id) {
        // ...
    }
    
  4. @RequestParam

    @RequestMapping("/buy")
    Car buyCar(@RequestParam(defaultValue = "5") int seatCount) {
        // ...
    }
    

    与@RequestParam 类似的注解,还有@CookieValue 和@RequestHeader ,可以获取 cookie 和 headers。

Response Handling Annotations

  1. @ResponseBody

    @ResponseBody
    @RequestMapping("/hello")
    String hello() {
        return "Hello World!";
    }
    
  2. @ExceptionHandler

    自定义错误处理方法

    @ExceptionHandler(IllegalArgumentException.class)
    void onIllegalArgumentException(IllegalArgumentException exception) {
        // ...
    }
    
  3. @ResponseStatus

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    void onIllegalArgumentException(IllegalArgumentException exception) {
        // ...
    }
    

Other Web Annotations

  1. @Controller

  2. @RestController

    @RestController 包含@Controller 和@ResponseBody

    @Controller
    @ResponseBody
    class VehicleRestController {
        // ...
    }
    
    @RestController
    class VehicleRestController {
        // ...
    }
    
  3. @ModelAttribute

    @ModelAttribute 可以用在方法参数或者方法上。

    @ModelAttribute methods are invoked before the controller methods annotated with @RequestMapping are invoked

    The View

    <form:form method="POST" action="/spring-mvc-basics/addEmployee"
      modelAttribute="employee">
        <form:label path="name">Name</form:label>
        <form:input path="name" />
         
        <form:label path="id">Id</form:label>
        <form:input path="id" />
         
        <input type="submit" value="Submit" />
    </form:form>
    

    The Controller

    @Controller
    @ControllerAdvice
    public class EmployeeController {
     
        private Map<Long, Employee> employeeMap = new HashMap<>();
     
        @RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
        public String submit(
          @ModelAttribute("employee") Employee employee,
          BindingResult result, ModelMap model) {
            if (result.hasErrors()) {
                return "error";
            }
            model.addAttribute("name", employee.getName());
            model.addAttribute("id", employee.getId());
     
            employeeMap.put(employee.getId(), employee);
     
            return "employeeView";
        }
     
        @ModelAttribute
        public void addAttributes(Model model) {
            model.addAttribute("msg", "Welcome to the Netherlands!");
        }
    }
    

    The Model

    @XmlRootElement
    public class Employee {
     
        private long id;
        private String name;
     
        public Employee(long id, String name) {
            this.id = id;
            this.name = name;
        }
     
        // standard getters and setters removed
    }
    

    Results View

    <h3>${msg}</h3>
    Name : ${name}
    ID : ${id}
    
  4. @CrossOrigin

    @CrossOrigin
    @RequestMapping("/hello")
    String hello() {
        return "Hello World!";
    }
    
    @CrossOrigin(maxAge = 3600)
    @RestController
    @RequestMapping("/account")
    public class AccountController {
     
        @CrossOrigin("http://example.com")
        @RequestMapping("/{id}")
        public Account retrieve(@PathVariable Long id) {
            // ...
        }
     
        @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
        public void remove(@PathVariable Long id) {
            // ...
        }
    }
    

    Global CORS Configuration

    JavaConfig

    @Configuration
    @EnableWebMvc
    public class WebConfig implements WebMvcConfigurer {
     
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**");
        }
    }
    

    XML Namespace

    <mvc:cors>
        <mvc:mapping path="/**" />
    </mvc:cors>
    
    <mvc:cors>
     
        <mvc:mapping path="/api/**"
            allowed-origins="http://domain1.com, http://domain2.com"
            allowed-methods="GET, PUT"
            allowed-headers="header1, header2, header3"
            exposed-headers="header1, header2" allow-credentials="false"
            max-age="123" />
     
        <mvc:mapping path="/resources/**"
            allowed-origins="http://domain1.com" />
     
    </mvc:cors>
    

Spring Boot Annotations

  1. @SpringBootApplication

    @SpringBootApplication 包含@Configuration、@EnableAutoConfiguration、@ComponentScan

    @SpringBootApplication
    class VehicleFactoryApplication {
     
        public static void main(String[] args) {
            SpringApplication.run(VehicleFactoryApplication.class, args);
        }
    }
    
  2. @EnableAutoConfiguration

    It means that Spring Boot looks for auto-configuration beans on its classpath and automatically applies them.

    注意:必须与@Configuration 注解一起使用

    @Configuration
    @EnableAutoConfiguration
    class VehicleFactoryConfig {}
    

Auto-Configuration Conditions

  1. @ConditionalOnClass and @ConditionalOnMissingClass

    the annotation’s argument is present/absent

    @Configuration
    @ConditionalOnClass(DataSource.class)
    class MySQLAutoconfiguration {
        //...
    }
    
  2. @ConditionalOnBean and @ConditionalOnMissingBean

    the presence or absence of a specific bean

    @Bean
    @ConditionalOnBean(name = "dataSource")
    LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        // ...
    }
    
  3. @ConditionalOnProperty

    values of properties

    @Bean
    @ConditionalOnProperty(
        name = "usemysql", 
        havingValue = "local"
    )
    DataSource dataSource() {
        // ...
    }
    
  4. @ConditionalOnResource

    a specific resource is present:

    @ConditionalOnResource(resources = "classpath:mysql.properties")
    Properties additionalProperties() {
        // ...
    }
    
  5. @ConditionalOnWebApplication and @ConditionalOnNotWebApplication

    the current application is or isn’t a web application

    @ConditionalOnWebApplication
    HealthCheckController healthCheckController() {
        // ...
    }
    
  6. @ConditionalExpression

    the SpEL expression is evaluated to true

    @Bean
    @ConditionalOnExpression("${usemysql} && ${mysqlserver == 'local'}")
    DataSource dataSource() {
        // ...
    }
    
  7. @Conditional

    For even more complex conditions, we can create a class evaluating the custom condition. We tell Spring to use this custom condition with @Conditional

    @Conditional(HibernateCondition.class)
    Properties additionalProperties() {
        //...
    }
    

Spring Scheduling Annotations

  1. @EnableAsync

    定义异步执行功能,必须与@Configuration 一起使用

    @Configuration
    @EnableAsync
    class VehicleFactoryConfig {}
    

    执行@Async 定义的方法

  2. @EnableScheduling

    必须与@Configuration 一起使用

    @Configuration
    @EnableScheduling
    class VehicleFactoryConfig {}
    

    执行@Scheduled 定义的方法

  3. @Async

    @Async
    void repairCar() {
        // ...
    }
    

    使用@Async 定义的方法要遵循以下限制

    1. 必须是 public 方法
    2. 同一类中,自调用不起作用,也就是同一类中,直接调用另一个异步方法不起作用
  4. @Scheduled

    @Scheduled(fixedRate = 10000)
    void checkVehicle() {
        // ...
    }
    
    @Scheduled(fixedRate = 10000)
    @Scheduled(cron = "0 * * * * MON-FRI")
    void checkVehicle() {
        // ...
    }
    

    注意:使用@Scheduled 注解的方法返回类型应该是 void 类型的

  5. @Schedules

    @Schedules({ 
      @Scheduled(fixedRate = 10000), 
      @Scheduled(cron = "0 * * * * MON-FRI")
    })
    void checkVehicle() {
        // ...
    }
    

Spring Bean Annotations

  1. @ComponentScan

    @Configuration
    @ComponentScan(basePackages = "com.baeldung.annotations")
    class VehicleFactoryConfig {}
    
    @Configuration
    @ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
    class VehicleFactoryConfig {}
    
    @Configuration
    @ComponentScan(basePackages = "com.baeldung.annotations")
    @ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
    class VehicleFactoryConfig {}
    
    @Configuration
    @ComponentScans({ 
      @ComponentScan(basePackages = "com.baeldung.annotations"), 
      @ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
    })
    class VehicleFactoryConfig {}
    

    使用XML方法

    <context:component-scan base-package="com.baeldung" />
    
  2. @Component

    @Component
    class CarUtility {
        // ...
    }
    
  3. @Repository

    @Repository
    class VehicleRepository {
        // ...
    }
    
  4. @Service

    @Service
    public class VehicleService {
        // ...    
    }
    
  5. @Controller

    @Controller
    public class VehicleController {
        // ...
    }
    
  6. @Configuration

    @Configuration
    class VehicleFactoryConfig {
     
        @Bean
        Engine engine() {
            return new Engine();
        }
     
    }
    

AOP注解

@Aspect
@Component
public class PerformanceAspect {
    @Pointcut("within(@org.springframework.stereotype.Repository *)")
    public void repositoryClassMethods() {};
 
    @Around("repositoryClassMethods()")
    public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint) 
      throws Throwable {
        long start = System.nanoTime();
        Object returnValue = joinPoint.proceed();
        long end = System.nanoTime();
        String methodName = joinPoint.getSignature().getName();
        System.out.println(
          "Execution of " + methodName + " took " + 
          TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
        return returnValue;
    }
}

引自: www.baeldung.com/spring-core…