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.