1. Java custom annotations and Spring
Java annotations, as a kind of metadata information of program elements (classes, member variables, member methods, etc.), have no impact on the execution of the program itself. Through custom annotations, you can add special declarations to program elements.
As a platform for building enterprise-level applications, Spring provides rich functions. Combining Java's custom annotations with Spring to implement the parsing and processing of annotations in specific scenarios can reduce the coupling degree of applications and improve the scalability of the program.
2. Application scenarios
The following summarizes several application scenarios and only explains the general idea (ps: Not all scenarios have been practiced in the project)
2.1 Login, permission blocking
In web projects, login interception and permission interception are a cliché function. Through custom login annotations or permission annotations, parse annotations in the custom interceptor to realize login and permission interception functions.
This method of use has simple configuration, high flexibility and low code coupling.
2.2 Timing task management
During the system construction process, there will be various timed tasks requirements, and the centralized management of timed tasks can more efficiently maintain the operation of the system.
The custom timing task annotations in the RepeatingAnnotations chapter of the official Java annotation document, can realize the timing task declaration of business methods. Combined with Spring's container postprocessor BeanPostProcessor (ps: Spring container postprocessor will be discussed in the next article), parsing custom annotations. The parsed annotation information is then used to build the runtime timing task using QuartzAPI, which can complete the runtime creation and centralized management of the timing task.
This method can avoid defining the configuration of Quartz timing tasks and improve system scalability.
2.3 Data source specification for multi-data source routing
AbstractRoutingDataSource provided by Spring implements dynamic routing of multiple data sources and can be applied under a master-slave separation architecture. By specifying different data sources for different methods, dynamic routing of data sources is realized (for example: reading methods go from the slave database data source, writing methods go from the main database data source). How to identify the data source type corresponding to different methods can be implemented using custom annotations. The routing function of the data source is realized by analyzing the corresponding data source type declared on the method.
This method avoids pattern matching parsing of methods (for example: beginning with select, beginning with update, etc.), and the declaration is more flexible.
Custom annotations
Let’s take a look at the simplest example. In the process of using SpringWeb applications, we inevitably use @Controller, @Service, @Repository and other annotations to define JavaBeans. So how can you define an annotation yourself? Spring can load automatically. So there is the first example.
@Target({ ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface MyComponent { String value() default "";} @Configurationpublic class ComponentAnnotationTest { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();annotationConfigApplicationContext.register(ComponentAnnotationTest.class); annotationConfigApplicationContext.refresh(); InjectClass injectClass = annotationConfigApplicationContext.getBean(InjectClass.class); injectClass.print(); } @MyComponent public static class InjectClass { public void print() { System.out.println("hello world"); } }}Run this example and you will find that the class annotated by @MyComponent is also loaded in by Spring and can be used normally as an ordinary JavaBean. Checking Spring's source code, you will find that Spring uses ClassPathScanningCandidateComponentProvider to scan package. This class has such annotation.
A component provider that scans the classpath from a base package. It then applies exclude and include filters to the resulting classes to find candidates.
The registerDefaultFilters method of this class has several lines of code
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. }}Here you will find that Spring's use of scanning class information will only judge the class annotated by @Component, so any custom annotation can be scanned by Spring and injected into the container as long as it is equipped with @Component (of course, there must be a String value() default ""; method, because Spring's beans are uniquely marked with beanName).
Summarize
The above is all about this article's brief discussion on the application of custom annotations in Spring, I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!