我們很多時候需要自定義注解來實現(xiàn)一些特殊的功能,比如配合Spring @Aspect實現(xiàn)對數(shù)據(jù)統(tǒng)一加解密的切面編程短蜕。那么我們如何讓我們自定義注解修飾的類被spring識別并且被注入到IOC容器中呢壁顶?我們這里提供三種方式康铭。
當然棒卷,首先我們得自定義一個做注解, 并且讓它修飾一個類
package com.luca.annotation;
import java.lang.annotation.*;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface PersonalMapper {
}
package com.luca.annotation;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
@PersonalMapper
public class UserMapper {
}
至于如何檢測這個bean是否被注入到了容器中修档,我們可以通過ApplicationContext獲取并且判斷
package com.luca;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.stream.Stream;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
@SpringBootApplication
@EnableScheduling
public class DemoApplication implements CommandLineRunner {
@Autowired
private ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(beanName->{
if (beanName.equals("userMapper")){
System.out.println("userMapper bean exist");
}
});
}
}
方式1:@Component
我們可以直接在自定義注解里面添加@Component注解
package com.luca.annotation;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Component
public @interface PersonalMapper {
}
我們運行程序碧绞,發(fā)現(xiàn)這個bean的確存在
2021-10-01 14:52:20.741 INFO 1042 --- [ main] com.luca.DemoApplication : Starting DemoApplication on LM-SHC-15009711 with PID 1042 (/Users/hzzou/workpace/v3debt/55/luca/test1/target/classes started by hzzou in /Users/hzzou/workpace/v3debt/55/luca)
2021-10-01 14:52:20.743 INFO 1042 --- [ main] com.luca.DemoApplication : No active profile set, falling back to default profiles: default
2021-10-01 14:52:20.999 INFO 1042 --- [ main] o.s.c.a.ConfigurationClassPostProcessor : Cannot enhance @Configuration bean definition 'definitionRegistryPostProcessor' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
2021-10-01 14:52:21.135 INFO 1042 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler'
2021-10-01 14:52:21.153 INFO 1042 --- [ main] com.luca.DemoApplication : Started DemoApplication in 0.684 seconds (JVM running for 2.241)
userMapper bean exist
方式二 實現(xiàn)BeanDefinitionRegistryPostProcessor接口
我們通過實現(xiàn)BeanDefinitionRegistryPostProcessor接口的方式,自定義掃描路徑吱窝,讓bean被注入到容器中讥邻。
package com.luca.annotation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
@Configuration
public class DefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
MyBeanDefinitionScanner scanner = new MyBeanDefinitionScanner(beanDefinitionRegistry, false);
scanner.addIncludeFilter(new AnnotationTypeFilter(PersonalMapper.class));
scanner.doScan("com.luca.annotation");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
方式三 實現(xiàn)ImportBeanDefinitionRegistrar接口
這種方式其實和第二種方式類似,都是找到一個切入點院峡,讓spring掃描到被自定義注解修飾的類兴使,完成bean的注入
package com.luca.annotation;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
public class PersonalAutoConfigureRegistrar implements ImportBeanDefinitionRegistrar{
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
MyBeanDefinitionScanner scanner = new MyBeanDefinitionScanner(beanDefinitionRegistry, false);
scanner.addIncludeFilter(new AnnotationTypeFilter(PersonalMapper.class));
scanner.doScan("com.luca.annotation");
}
}
package com.luca.annotation;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import java.util.Set;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
public class MyBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
public MyBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
super(registry, useDefaultFilters);
}
@Override
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
return super.doScan(basePackages);
}
}
package com.luca.config;
import com.luca.annotation.PersonalAutoConfigureRegistrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author: Luca
* @Date: 2021/9/30
* @Description:
*/
@Configuration
@Import(PersonalAutoConfigureRegistrar.class)
public class MyConfig {
}