Spring Boot自定义注解扫描器 Spring Boot自定义注解扫描器

Spring Boot自定义注解扫描器

这个还挺实用的,会将指定包下的相应的类加载至Spring容器中,刚好我这边也有一个独立抽取出来的权限模块也想实现这样的功能(当然可以使用@EnableXX的方式,但是注入的组件太多了,直接包扫描直接点),而不是使用@ComponentScan或者是scanBasePackages必须指定某个包,这样显得太low了,使用注解自动扫描多好。

先来看看@MapperScan是怎么实现的:

没有什么特别的,引入了MapperScannerRegistrar:

中间有很多其他的代码都不用管,直接看最关键的:

定义了一个Mapper的Scanner:

然后调用doScan()方法即可:

而doScan()方法实际上就是Spring的核心扫描器ClassPathBeanDefinitionScanner的方法,而tkMybatis中定义了一个ClassPathMapperScanner继承了ClassPathBeanDefinitionScanne重写了doScan()方法,我们就可以照葫芦画瓢了。

自定义注解

自定义Registrar


  
  
  1. import lombok.extern.slf4j.Slf4j;
  2. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
  3. import org.springframework.context.EnvironmentAware;
  4. import org.springframework.context.ResourceLoaderAware;
  5. import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
  6. import org.springframework.core.annotation.AnnotationAttributes;
  7. import org.springframework.core.env.Environment;
  8. import org.springframework.core.io.ResourceLoader;
  9. import org.springframework.core.type.AnnotationMetadata;
  10. import org.springframework.util.StringUtils;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. /**
  14. * @author Dongguabai
  15. * @date 2018/8/15 13:36
  16. */
  17. @Slf4j
  18. public class DgbSecurityScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
  19. private ResourceLoader resourceLoader;
  20. private Environment environment;
  21. @Override
  22. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  23. AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(DgbSecurityScan.class.getName()));
  24. ClassPathDgbSecurityScanner scanner = new ClassPathDgbSecurityScanner(registry);
  25. // this check is needed in Spring 3.1
  26. if (resourceLoader != null) {
  27. scanner.setResourceLoader(resourceLoader);
  28. }
  29. List<String> basePackages = new ArrayList<String>();
  30. for (String pkg : annoAttrs.getStringArray( "basePackages")) {
  31. if (StringUtils.hasText(pkg)) {
  32. basePackages.add(pkg);
  33. }
  34. }
  35. scanner.doScan(StringUtils.toStringArray(basePackages));
  36. }
  37. @Override
  38. public void setEnvironment(Environment environment) {
  39. this.environment = environment;
  40. }
  41. @Override
  42. public void setResourceLoader(ResourceLoader resourceLoader) {
  43. this.resourceLoader = resourceLoader;
  44. }
  45. }

自定义Scanner


  
  
  1. import org.springframework.beans.factory.config.BeanDefinitionHolder;
  2. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
  3. import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
  4. import org.springframework.core.env.Environment;
  5. import org.springframework.core.io.ResourceLoader;
  6. import org.springframework.lang.Nullable;
  7. import java.util.Arrays;
  8. import java.util.Set;
  9. /**
  10. * @author Dongguabai
  11. * @date 2018/8/15 13:40
  12. */
  13. public class ClassPathDgbSecurityScanner extends ClassPathBeanDefinitionScanner {
  14. public ClassPathDgbSecurityScanner(BeanDefinitionRegistry registry) {
  15. super(registry);
  16. }
  17. public ClassPathDgbSecurityScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
  18. super(registry, useDefaultFilters);
  19. }
  20. public ClassPathDgbSecurityScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
  21. super(registry, useDefaultFilters, environment);
  22. }
  23. public ClassPathDgbSecurityScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {
  24. super(registry, useDefaultFilters, environment, resourceLoader);
  25. }
  26. /**
  27. * Calls the parent search that will search and register all the candidates.
  28. * Then the registered objects are post processed to set them as
  29. * MapperFactoryBeans
  30. */
  31. @Override
  32. public Set<BeanDefinitionHolder> doScan(String... basePackages) {
  33. Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
  34. if (beanDefinitions.isEmpty()) {
  35. logger.warn( "No DgbSecurity Spring Componet was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
  36. }
  37. return beanDefinitions;
  38. }
  39. }

最后将注解放到Spring Boot启动类上即可。

因为是临时突然想到这个,代码应该有不少可以优化的地方,以后再看吧。

========================================================================================

使用这个方式用在基于Spring Security的权限模块是可以的,但是用在基于Quartz的调度模块一直出问题,经过debug发现是可以扫描成功并且是可以注册的,但是启动过程中执行调度任务的时候一直出问题,异常显示为create Bean找不到那个Bean,一直无法理解。但是在别的模块是可以正常使用的。

				<script>
					(function(){
						function setArticleH(btnReadmore,posi){
							var winH = $(window).height();
							var articleBox = $("div.article_content");
							var artH = articleBox.height();
							if(artH > winH*posi){
								articleBox.css({
									'height':winH*posi+'px',
									'overflow':'hidden'
								})
								btnReadmore.click(function(){
									articleBox.removeAttr("style");
									$(this).parent().remove();
								})
							}else{
								btnReadmore.parent().remove();
							}
						}
						var btnReadmore = $("#btn-readmore");
						if(btnReadmore.length>0){
							if(currentUserName){
								setArticleH(btnReadmore,3);
							}else{
								setArticleH(btnReadmore,1.2);
							}
						}
					})()
				</script>
				</article>

猜你喜欢

转载自blog.csdn.net/jianghuchuanke/article/details/83623849