Spring自定义扩展

借助@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) 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) 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自定义扩展)