• Spring--注解


    一、简介

    Spring注解是一种元数据形式的代码,用于提供配置信息,从而减少XML配置文件的使用。Spring框架提供了一系列的注解,用于简化Spring应用程序的开发。通过使用这些注解,开发者可以在不编写大量XML配置的情况下,实现对Spring容器中bean的声明和管理、自动装配依赖、声明事务管理等功能。

    二、常用注解

    1. @Component:表示一个类是Spring容器管理的组件,可以被自动扫描并注册到Spring应用上下文中。
    2. @Controller:是@Component的特化,用于标注控制层的组件,处理用户请求和返回响应。
    3. @RestController:是@Controller和@ResponseBody的组合,简化了RESTful Web服务的编写。
    4. @Service:是@Component的特化,用于标注服务层的组件。
    5. @Repository:是@Component的特化,用于标注数据访问层的组件,通常与数据库交互。
    6. @Configuration:表示一个类是配置类,可以包含一个或多个@Bean注解的方法。
    7. @Bean:表示一个方法产生一个bean,该方法的返回值将被注册到Spring应用上下文中。
    8. @Autowired:用于自动注入依赖关系,它可以应用于字段、构造函数、setter方法等。
    9. @Qualifier:与@Autowired结合使用,指定要注入的确切的bean实例。
    10. @RequestMapping:用于映射Web请求到控制器的处理方法,可以指定URL模式、HTTP方法等。
    11. @PathVariable:用于从URL的一部分中提取变量值,并将其作为方法参数。
    12. @ResponseBody:指示方法的返回值应该直接写入HTTP响应体中,通常与@RequestMapping一起使用。
    13. @Transactional:用于声明事务的边界,确保事务的一致性和原子性。
    14. @EnableTransactionManagement:启用声明式事务管理。

    三、元注解

    Spring框架中的元注解是指那些用于注解其他注解的注解。它们提供了一种机制来定义新的注解,并指定这些新注解的行为和作用范围。Spring提供了几个核心的元注解,这些元注解可以用来创建自定义注解,以下是一些常用的Spring元注解:

    1. @Target:指定自定义注解可以应用于哪些Java元素,如类、方法、构造函数、字段或注解等。它接受ElementType枚举的一个或多个值作为参数,常用的枚举值有:
      • ElementType.TYPE:说明该注解只能被声明在一个类前;
      • ElementType.FIELD:说明该注解只能被声明在一个类的字段前;
      • ElementType.METHOD:说明该注解只能被声明在一个类的方法前;
      • ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前;
      • ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前;
      • ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前;
      • ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前;
      • ElementType.PACKAGE:说明该注解只能声明在一个包名前。
    2. @Retention:确定自定义注解在何种生命周期内有效。它有三个可能的值:
      • RUNTIME:表示注解在运行时依然存在;
      • CLASS:表示注解仅在编译后的.class文件中保留;
      • SOURCE:表示注解仅在源代码中有效,编译时会被丢弃。
    3. @Documented:指示Javadoc工具应该记录自定义注解。当你希望在生成的API文档中包含自定义注解时,应该使用这个元注解。
    4. @Inherited:表示自定义注解可以被子类继承。如果一个注解被标注为@Inherited,那么其父类上的该注解也会出现在子类上。

    四、注解的原理

    Spring框架中的注解原理基于Java的反射API和代理技术,主要涉及以下几个方面:

    1. 注解扫描:

      • Spring容器启动时,会根据@ComponentScan注解指定的基础包路径,扫描类路径下所有带有特定注解(如@Component、@Service、@Repository、@Controller等)的类。
      • 这些注解通常会通过@Component或其特化注解来标记Spring容器应该管理的组件。
    2. Bean的实例化和注册:

      • 被扫描到的带有Spring管理注解的类将被实例化。如果该类有无参构造函数,Spring会使用默认无参构造函数创建实例;如果没有无参构造函数,可能会使用CGLIB等字节码操作库进行实例化。
      • 创建的实例会被注册到Spring容器中,以便之后进行依赖注入。
    3. 依赖注入:

      • Spring容器会根据注解如@Autowired、@Inject、@Resource等来确定依赖关系,并通过反射机制将依赖注入到目标Bean中。
      • 如果依赖是由方法参数或者构造函数指定的,Spring会尝试匹配相应类型的Bean进行注入。
      • 如果依赖是字段,Spring会直接设置字段的值。
    4. 代理创建:

      • 对于需要AOP(面向切面编程)功能的Bean,Spring会创建一个代理对象。这个代理对象会拦截对目标Bean的调用,并在适当的时机执行通知逻辑。
      • 代理可以是JDK动态代理(仅适用于实现了接口的类)或者基于CGLIB的代理(适用于所有类,包括抽象类和没有实现接口的类)。
    5. Bean的生命周期管理:

      • Spring容器负责管理Bean的整个生命周期。在Bean初始化时,会调用初始化方法(如@PostConstruct注解的方法)。
      • 在Bean销毁时,会调用清理方法(如@PreDestroy注解的方法)。
    6. 事件发布和监听器机制:

      • Spring容器在Bean的生命周期事件发生时,会发布相应的事件,比如ContextRefreshedEvent、ContextClosedEvent等。
      • 可以注册监听器(Listener)来响应这些事件,从而实现一些自定义的逻辑。

    五、自定义注解

    自定义注解是通过使用@interface关键字来创建的。自定义注解可以用来为类、方法、变量等添加元数据信息。自定义注解本身也可以被其他注解修饰。以下是创建和使用自定义注解的基本步骤:

    1. 定义注解:使用@interface关键字来定义一个注解类型。可以指定注解的保留策略(@Retention)、允许的目标(@Target)等。
    import java.lang.annotation.*;
    
    @Retention(RetentionPolicy.RUNTIME)  // 注解在运行时依然存在
    @Target(ElementType.FIELD) // 注解作用于字段上
    @Documented  // 注解将包含在JavaDoc中
    @Inherited   // 注解来允许注解被继承
    public @interface CustomAnnotation {
        String value();
        String name() default "defaultName";  // 为注解的元素提供默认值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 使用注解:在类、方法、变量等元素上使用定义好的注解。
    public class ExampleClass {
        @CustomAnnotation("exampleValue")
        private String exampleField;
    }
    
    • 1
    • 2
    • 3
    • 4
    1. 处理注解:在程序运行时,可以使用反射API来检测注解,并根据注解的信息执行相应的逻辑。
    import java.lang.reflect.Field;
    
    public class AnnotationProcessor {
        public static void processAnnotations(Object object) throws IllegalAccessException {
            Class<?> clazz = object.getClass();
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(CustomAnnotation.class)) {
                    CustomAnnotation annotation = field.getAnnotation(CustomAnnotation.class);
                    String value = annotation.value();
                    System.out.println("Found annotation with value: " + value);
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    六、自定义注解与AOP整合

    在Spring框架中,通过将自定义注解和AOP结合使用,可以对业务逻辑进行非侵入式的增强。下面是如何创建自定义注解并将其应用于切面的详细步骤:

    1. 定义自定义注解:首先,需要定义一个自定义注解,该注解可以包含一些元数据,如目标方法的名称、执行顺序等。
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface LogExecutionTime {
        // 可以定义更多的属性,例如优先级等
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 创建切面类:接着,创建一个切面类,并定义通知(Advice),通知是指在切点匹配的方法执行前后或抛出异常时执行的代码块。
    @Aspect
    public class LoggingAspect {
    
        // 定义切点表达式,匹配带有LogExecutionTime注解的方法
        @Pointcut("@annotation(com.example.annotation.LogExecutionTime)")
        public void methodsAnnotatedWithLogExecutionTime() {}
    
        // 在目标方法前执行的通知
        @Before("methodsAnnotatedWithLogExecutionTime()")
        public void logBefore(JoinPoint joinPoint) {
            long start = System.currentTimeMillis();
            System.out.println("Starting method: " + joinPoint.getSignature().getName());
        }
    
        // 在目标方法后执行的通知
        @After("methodsAnnotatedWithLogExecutionTime()")
        public void logAfter(JoinPoint joinPoint) {
            long end = System.currentTimeMillis();
            System.out.println("Ending method: " + joinPoint.getSignature().getName() + " in " + (end - start) + "ms");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    1. 启用AOP支持:在Spring配置文件中,或者使用Java配置来启用AOP支持。
    @Configuration
    @EnableAspectJAutoProxy
    public class AppConfig {
        // 其他配置...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 使用自定义注解:最后,将自定义注解应用于需要被切面处理的方法上。
    @Service
    public class SomeService {
    
        @LogExecutionTime
        public void someBusinessMethod() {
            // 业务逻辑
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在上述示例中,LogExecutionTime注解被定义并用于标记特定的方法。LoggingAspect切面类定义了两个通知方法:logBefore和logAfter,它们分别在带有LogExecutionTime注解的方法执行前后执行。通过@EnableAspectJAutoProxy注解,Spring容器会自动为切面生成代理对象,从而使得通知能够在目标方法执行时被触发。通过这种方式,可以非常灵活地为不同的业务逻辑添加额外的行为,而无需修改原有代码,这正是AOP的强大之处。

  • 相关阅读:
    轴承故障分类方法之CNN+SVM和ELM
    静态代理IP是什么?一文看懂静态代理IP
    Maven 插件之 docker-maven-plugin 的使用
    Ubuntu安装Android Studio
    【Python脚本进阶】2.1、端口扫描器(下):NMAP端口扫描
    verilog牛客网刷题代码汇总
    网络安全(黑客)自学
    电商数仓项目中各层的表
    异步编程详解(.NET)
    亚马逊运营纯干货:如何引流?亚马逊站外引流最全讲解
  • 原文地址:https://blog.csdn.net/qq_33807380/article/details/136691262