美文网首页
Spring自定义扩展

Spring自定义扩展

作者: coderlan | 来源:发表于2018-04-23 18:03 被阅读0次

    借助@Component

    Spring本身的@Component实现,依赖于ClassPathScanningCandidateComponentProvider在指定的路径下进行扫描,并且完成自动加载。
    查看ClassPathScanningCandidateComponentProvider的源码,可以看到Spring默认加载了一个注解过滤器,来过滤@Component的类。

    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.  
       }
    }
    

    这里只加载了@Component注解的过滤器,那@Service、@Controller这些注解呢?看了下@Service的源码,就知道了@Service其实是借助了@Component来实现加载的。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Service {
    
        /**
         * The value may indicate a suggestion for a logical component name,
         * to be turned into a Spring bean in case of an autodetected component.
         * @return the suggested component name, if any
         */
        String value() default "";
    
    }
    

    这种方式比较局限,不能做一些定制。

    Spring启动之后,再把bean拿出来加工、定制

    SpringMVC就是使用这种方式,在Spring启动之后,遍历所有的bean,把带有@Controller的bean拿出来,构造UrlMapping。比如AbstractDetectingUrlHandlerMapping 。

    自定义扫描

    BeanFactoryPostProcessor 和ApplicationContextAware。
    Spring提供了一些的接口使程序可以嵌入Spring的加载过程。这个类中的继承ApplicationContextAware接口,Spring会读取ApplicationContextAware类型的的JavaBean,并调用setApplicationContext(ApplicationContext applicationContext)传入Spring的applicationContext。
    同样继承BeanFactoryPostProcessor接口,Spring会在BeanFactory的相关处理完成后调用postProcessBeanFactory方法,进行定制的功能。

    ClassPathBeanDefinitionScanner是Spring提供的一个ClassPath扫描器,其实也继承于ClassPathScanningCandidateComponentProvider,只不过ClassPathBeanDefinitionScanner需要一个BeanFactory或者ApplicationContext,在扫描到符合要求的类,就会加入到BeanFactory或者ApplicationContext中。

    至此,完成了自定义扫描功能,但是还没有对bean进行加工、定制,还需要使用到FactoryBean,普通的JavaBean是直接使用类的实例,但是如果一个Bean继承了这个借口,就可以通过getObject()方法来自定义实例的内容,在FactoryBeanTest的getObject()就通过代理了原始类的方法,自定义类的方法。

    总结一下:

    • ApplicationContextAware获取ApplicationContext
    • BeanFactoryPostProcessor 获取BeanFactory
    • ClassPathBeanDefinitionScanner提供了自定义扫描的入口(使用ApplicationContext和BeanFactory,并且启动自定义扫描)
    • FactoryBean对自己感兴趣的Bean进行增强处理

    相关文章

      网友评论

          本文标题:Spring自定义扩展

          本文链接:https://www.haomeiwen.com/subject/udyclftx.html