Explicação detalhada da anotação @inherited

1 [Pergunta suscitada]

Em um projeto Springboot, geralmente há uma classe de inicialização, e a classe de inicialização geralmente tem uma anotação chamada @SpringBootApplication (como mostrado na figura abaixo), e essa anotação é a anotação principal da classe de inicialização do projeto Springboot.

Abrimos o código fonte da anotação @SpringBootApplication, podemos ver que existe uma anotação @Inherited no código fonte, então qual é a função dessa anotação?

2【@código-fonte herdado】

Antes de entender a função da anotação, podemos dar uma olhada na explicação em inglês e na definição do código-fonte da anotação, que será mais propícia ao nosso entendimento da anotação.

(2.1) tradução herdada

 Antes de tudo, vamos ver a tradução (da tradução do Baidu), podemos ver que @inherited tem o significado de "herança" e "sucessão".

(2.2) @inherite código-fonte

Em seguida, abrimos o código fonte do herdado e podemos ver:

(1) A anotação atua em todo o programa em execução ( @Retention(RetentionPolicy.RUNTIME );

(2) Esta anotação só pode modificar anotações ( @Target({ElementType.ANNOTATION_TYPE}) ), portanto, é uma meta-anotação.

 Depois de entender a situação acima, podemos explorar ainda mais a anotação @inherited.

3【Exemplo】

Como é uma anotação sobre "herança", podemos pensar que também existe uma relação de herança entre classes Java. Podemos também criar duas classes, deixá-las ser uma relação pai-filho, e então criar duas anotações para atuar na Acima, a única diferença entre as duas anotações é a presença ou ausência da decoração @Inherited.

Criamos a classe pai Father e a classe filha Child como classes experimentais.

(3.1) Classe do pai

(3.2) Classe filho (herdando classe Pai)

 Além disso, personalizamos mais duas anotações, @HasInherited e @NoInherited, para verificar o resultado, a primeira anotação contém a anotação @Inherited, a última vice-versa.

Como a definição da anotação precisa especificar o escopo da ação e o ciclo de vida da ação, podemos também especificar que ambas as anotações atuam na classe e em todo o ciclo de vida do código em execução, de modo que a única diferença entre as duas seja a presença ou ausência da anotação @Inherited.

(3.3) @HasInherited (com anotação @Inherited)

(3.4) @NoInherited (sem anotação @Inherited)

 

 4【Verificação de teste】

(4.1) Criar classe de teste de teste

Vamos escrever outra classe de teste Test para obter todas as informações de anotação nas classes experimentais (Pai e Filho).

package com.test.inherited;

import java.lang.annotation.Annotation;

public class Test {

    public static void main(String[] args) {
        // 打印父类注解信息
        Annotation[] fatherAnnotations = Father.class.getAnnotations();
        System.out.println("------- 父类 Father 信息 --------");
        System.out.println("父类注解个数:" + fatherAnnotations.length);
        for (Annotation fa : fatherAnnotations) {
            System.out.println(fa.annotationType().getSimpleName());
        }
        // 打印子类注解信息
        Annotation[] childAnnotations = Child.class.getAnnotations();
        System.out.println("------- 子类 Child 信息 --------");
        System.out.println("子类注解个数:" + childAnnotations.length);
        for (Annotation ca: childAnnotations) {
            System.out.println(ca.annotationType().getSimpleName());
        }
    }

}

 (4.2) Validação com anotação @Inherited

Primeiro, apenas anotamos a classe pai com @HasInherited, a subclasse não a processa e, em seguida, executamos a classe de teste Test.

@HasInherited
public class Father {

}

O console final imprime o seguinte:

------- 父类 Father 信息 --------
父类注解个数:1
HasInherited
------- 子类 Child 信息 --------
子类注解个数:1
HasInherited

 (4.3) Nenhuma validação de anotação @Inherited

Nós apenas anotamos a classe pai com @NoInherited, a subclasse não a processa e então executa a classe de teste Test.

@NoInherited
public class Father {

}

A impressão final do console é a seguinte:

------- 父类 Father 信息 --------
父类注解个数:1
NoInherited
------- 子类 Child 信息 --------
子类注解个数:0

(4.4) Conclusão

Após a demonstração acima, não é difícil para nós chegar à conclusão final.

Conclusão: Se uma anotação modificada pela anotação @Inherited atua em uma classe, suas subclasses podem herdar a anotação. Por outro lado, se uma anotação não for modificada pela anotação @Inherited, seu escopo só poderá ser a classe atual e suas subclasses não poderão ser herdadas.

5. [Modifique a classe de inicialização do Springboot]

Como a anotação @SpringBootApplication também contém a anotação @Inherited, para a conclusão acima, podemos tentar modificar a classe de inicialização Springboot. Podemos escrever uma subclasse para herdar a classe de inicialização original e remover o método mian de inicialização original. , add para a subclasse para ver se pode iniciar com sucesso?

(5.1) Antes de modificar a classe de inicialização do Springboot

A classe de inicialização é mostrada na figura:

Comece a imprimir da seguinte forma:

(5.2) Depois de modificar a classe de inicialização do Springboot

A classe de inicialização original (somente a anotação @SpringBootApplication é mantida)

Classe de sub-inicialização (sem anotações)

 Comece a imprimir da seguinte forma:

 Pode-se ver que de fato foi iniciado OK, o que também verifica nosso raciocínio.

6【Resumo】

Quando definimos uma anotação que atua em uma classe no futuro, se quisermos que a anotação também atue em suas subclasses, podemos usar @Inherited para modificá-la.

 

Acho que você gosta

Origin blog.csdn.net/sunnyzyq/article/details/119736442
Recomendado
Clasificación