likes
comments
collection
share

spring中的基本概念

作者站长头像
站长
· 阅读数 19

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第3篇文章,点击查看活动详情

1.BeanDefinition

主要作用是用来封装bean的信息:类型,是否是懒加载,是否是单例等等。 在spring中BeanDefinition是一个接口,它会有各种各样的实现类,这里我们只需要知道,它就是用来封装bean基本信息的就行了。

spring中的基本概念

2.声明式定义bean 编程式定义bean,

声明式定义bean: @Bean @Component 或者是xml 中的bena标签 编程式定义bean: 就是使用代码来注册bean生命bean的一些信息:单例,懒加载,等等。 例如:

public static void main(String[] args) {
      //ApplicationContext applicationContext = new ApplicationContext(UserService.class);
      //编程式
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(UserService.class);
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(UserService.class);
      context.registerBeanDefinition("userService",beanDefinition);
      //
      UserService userService =  (UserService)context.getBean("userService");
      userService.test();
   }
}

3. 读取器:AnnotatedBeanDefinitionReader

这个类是beanDefinition 读取器,可以将类封装成一个beanDefinition ,然后放入到spring容器当中变成一个bena。

public class User {

  public void test(){
     System.out.println("123123123");
  }
}
public class Test {

  public static void main(String[] args) {
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

     AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
     //注册一个bean
     reader.register(User.class);
     User user = (User)context.getBean("user");
     user.test();
  }
}

我们看上面的代码,user类是没有加注解的,正常情况下是不可能加载到spring容器当中的。使用AnnotatedBeanDefinitionReader 的 register()方法就可以将User类变成beanDefinition然后放到spring容器当中。 我们看下这里面的源码:

reader.register(User.class);
/**
 * Register one or more component classes to be processed.
 * <p>Calls to {@code register} are idempotent; adding the same
 * component class more than once has no additional effect.
 * @param componentClasses one or more component classes,
 * e.g. {@link Configuration @Configuration} classes
 */
public void register(Class<?>... componentClasses) {
   for (Class<?> componentClass : componentClasses) {
      registerBean(componentClass);
   }
}
public void registerBean(Class<?> beanClass) {
   doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
      @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
      @Nullable BeanDefinitionCustomizer[] customizers) {
    //创建一个beanDefinition 
   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
      return;
   }

   abd.setInstanceSupplier(supplier);
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
   abd.setScope(scopeMetadata.getScopeName());
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    //处理类上的注解信息
   AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
   if (qualifiers != null) {
      for (Class<? extends Annotation> qualifier : qualifiers) {
         if (Primary.class == qualifier) {
            abd.setPrimary(true);
         }
         else if (Lazy.class == qualifier) {
            abd.setLazyInit(true);
         }
         else {
            abd.addQualifier(new AutowireCandidateQualifier(qualifier));
         }
      }
   }
   if (customizers != null) {
      for (BeanDefinitionCustomizer customizer : customizers) {
         customizer.customize(abd);
      }
   }

   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

我们可以看到这个注册方法中创建了一个beanDefinition:

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);

然后就是对这个beanDefinition 进行各种处理,以上就是这个类的主要作用。 我们看 AnnotationConfigApplicationContext 中的构造方法:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   this();
   register(componentClasses);
   refresh();
}
public AnnotationConfigApplicationContext() {
   StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
   this.reader = new AnnotatedBeanDefinitionReader(this);
   createAnnotatedBeanDefReader.end();
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

可以看到AnnotationConfigApplicationContext()方法中创建了一个 AnnotatedBeanDefinitionReader。并且register(componentClasses)方法中使用的就是这里创建的AnnotatedBeanDefinitionReader的注册方法。

4. 扫描器:ClassPathBeanDefinitionScanner

一般在创建spring容器的时候,会传一个配置类,配置类上会配置有扫描路径,spring就会知道要扫描哪个包下面的类。 那么在创建spring容器的时候不传配置类,可以通过 ClassPathBeanDefinitionScanner 的scan 方法传一个包路径,与传配置类的效果是一样的。

public class Test {

   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.refresh();
      ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
      scanner.scan("com.xl.service");
      User user = (User)context.getBean("user");
      user.test();
   }
}

5.GenericBeanDefinition 及其子类

ClassPathBeanDefinitionScanner和AnnotatedBeanDefinitionReader都会生成beanDefinition但是他们生成的类型是不一样的。 AnnotatedBeanDefinitionReader 对应的:AnnotatedGenericBeanDefinition ClassPathBeanDefinitionScanner 对应的:ScannedGenericBeanDefinition 这两个beanDefinition都继承了GenericBeanDefinition。

6.ApplicationContext 和 BeanFactory

spring中的基本概念

spring中的基本概念

对比下可以看到,ApplicationContext 继承了除beanFactory外的很多接口,beanFactory 只是一个单纯的接口。

  1. ApplicationContext 拥有BeanFactory的功能:创建bean 获取bean
  2. ApplicationContext 拥有事件发布(ApplicationEventPublisher),国际化(MessageSource),获取环境变量(EnvironmentCapable),获取某些资源(ResourcePatternResolver)的功能,
  3. BeanFactory 只拥有创建bena,获取bean的功能。

如果只是创建bean 和获取bean,那么使用beanFactory就可以了。

public class Test {

   public static void main(String[] args) {
      DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(User.class);
      beanFactory.registerBeanDefinition("user",beanDefinition);
      User user = (User)beanFactory.getBean("user");
      user.test();
   }
}

DefaultListableBeanFactory 是beanFactory的一个实现类。AnnotationConfigApplicationContext中使用的就这个实现类。

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

   private final DefaultListableBeanFactory beanFactory;

   @Nullable
   private ResourceLoader resourceLoader;

   private boolean customClassLoader = false;

   private final AtomicBoolean refreshed = new AtomicBoolean();


   /**
    * Create a new GenericApplicationContext.
    * @see #registerBeanDefinition
    * @see #refresh
    */
   public GenericApplicationContext() {
      this.beanFactory = new DefaultListableBeanFactory();
   }
   }

以上源码只是一部分,可以看到AnnotationConfigApplicationContext继承了GenericApplicationContext,GenericApplicationContext中的beanFactory类型是DefaultListableBeanFactory。 spring中的基本概念

从上面这个类图可以看到,DefaultListableBeanFactory实现了很多接口,这些接口每个都有不同的功能,下面列举了一部分。 AliasRegistry:可以给bean起别名。 SingletonBeanRegistry:单例bean注册的功能。 BeanDefinitionRegistry:注册beanDefinition的功能。 HierarchicalBeanFactory:获取父beanFactory的功能。 ListableBeanFactory:判断是否包含这个beanDefinition,获取beanDefinition的名字 等功能 AutowireCapableBeanFactory:自动注入的beanFactory

7.MetadataReader ClassMetadata AnnotationMetadata

ClassMetadata :类的元数据信息。可以通过它来获取类的很多信息:父类的名字,接口的名字等等。 AnnotationMetadata: 注解的元数据信息。主要是获取一个类上面注解的相关信息. 它们与beanDefinition是不一样的,beanDefinition 是获取不到父类的名字,接口的名字的。所以,ClassMetadata 和 AnnotationMetadata 相比较beanDefinition 可以获取类的信息要全的多。

public class Test {

   public static void main(String[] args) throws IOException {
      SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
      //创建一个metadataReader
      MetadataReader metadataReader = metadataReaderFactory.getMetadataReader("com.xl.service.User");
      //获取一个classMetadata
      ClassMetadata classMetadata = metadataReader.getClassMetadata();
      //获取类名
      System.out.println(classMetadata.getClassName());
      //获取内部类名
      System.out.println(classMetadata.getMemberClassNames()[0]);
      //获取一个annotationMetadata
      AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
      //获取类上注解的信息
      for (String type:annotationMetadata.getAnnotationTypes()){
         System.out.println(type);
      }
   }
}

8.includeFilters 和 excludeFilters

excludeFilters排除,typ 属性可以指定类,注解等。 classes属性要指定排除的具体类或者注解。指定之后,spring是不对排除的注解或者类做任何处理的。

includeFilters包含,如果一个类没有加注解那么它是不会成为bean(一般情况下),但是它被includeFilters指定包含了,也会被sprig加载容器中成为bean。 以下这个这个两个的基本用法。

@ComponentScan(value = "com.xl.service",
      includeFilters = {@ComponentScan.Filter(
         type = FilterType.ASSIGNABLE_TYPE,
         classes = User.class
      )})
public class AppConfig {
}
@ComponentScan(value = "com.xl.service",
      excludeFilters = {@ComponentScan.Filter(
         type = FilterType.ASSIGNABLE_TYPE,
         classes = User.class
      )})
public class AppConfig {
}
public class User {
   public void test(){
      System.out.println("123123123");
   }
}
public class Test {

   public static void main(String[] args)  {
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
      User user = (User)context.getBean("user");
      user.test();
   }
}

在spring中使用includeFilters, ClassPathScanningCandidateComponentProvider 类下registerDefaultFilters()方法中。 spring默认会添加一个includeFilters,只要在扫描的时候发现一个类上面带有@Component,它就会认为符合includeFilters,这个类就是一个bean,它就会解析这个类生成一个beanDefinition.

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.trace("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.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
   }
   catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
   }
}

9.FactoryBean

一个类实现了这个接口,那么在getBean的时候返回的是getObject()方法返回的bean。如果想获取原来的bean,getBean("&lynnFactoryBean")在名字前面加& 就可以。 并且这个返回的这个bean只经历初始化后这么一个过程,并没有经历完成的bean的生命周期。 以下是测试代码

@Component("user")
public class LynnFactoryBean implements FactoryBean<User> {
   @Override
   public User getObject() throws Exception {
      return new User();
   }

   @Override
   public Class<?> getObjectType() {
      return User.class;
   }
}
@Component
public class LynnPostProcessor implements BeanPostProcessor {

   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      if(beanName.equals("user")){
         System.out.println("qian  "+bean);
      }

      return bean;
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      if(beanName.equals("user")){
         System.out.println("hou:  "+bean);
      }
      return bean;
   }
}
@ComponentScan(value = "com.xl.service")
public class AppConfig {
}
@Aspect
@Component
public class LynnAspect {
   @Before("execution(public void com.xl.service.User.test())")
   public void  before(JoinPoint joinPoint){

   }
}
public class Test {

  public static void main(String[] args)  {
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
     //这个返回的是User类型的bean
     System.out.println(context.getBean("user"));
     //这个返回的是 LynnFactoryBean类型的bean
     //System.out.println(context.getBean("&lynnFactoryBean"));

  }
}

以上大致就是spring框架中一些基本概念,如有笔误还请指正。