Spring源码-核心概念介绍

4 篇文章 1 订阅
3 篇文章 0 订阅

提示:Spring整体源码架构前置核心概念解析。BeanDefinition、BeanPostProcessor、aop的底层原理、spring源码核心、BeanPostProcessor,最简单学源码。BeanDefinition、BeanDefinitionReader、ClassPathBeanDefinitionScanner、BeanFactory、ApplicationContext、MessageSource、事件发布、类型转换、排序、MetadataReader(元数据)、BeanPostProcessor、BeanFactoryPostProcessor、ExcludeFilter和IncludeFilter。、FactoryBean、BeanPostProcessor

前言


直接看spring源码的时候,会感觉很吃力。我们这里主要介绍一些,常用的spring中的组件以及核心概念。目的是通过看这个类的名字,就知道它大概是用来干嘛的,从而方便我们更轻松的阅读源码。本人水平有限,如有误导,欢迎斧正,一起学习,共同进步!


一、总体概览

这里主要是一些比较核心的功能点。

1、BeanDefinition

2、BeanDefinitionReader

3、ClassPathBeanDefinitionScanner

4、BeanFactory

5、ApplicationContext

6、MessageSource

7、事件发布

8、类型转换

9、排序

10、MetadataReader(元数据)

11、BeanPostProcessor

12、BeanFactoryPostProcessor

13、ExcludeFilter和IncludeFilter。

14、FactoryBean

15、BeanPostProcessor

二、详细介绍

1、BeanDefinition

beanDefinition 是一个接口,表示bean的定义,是bean的一些公共的属性。

  • class : bean的类型
  • scope : bean的作用域,单例或者多例
  • lazyInit : bean是否是懒加载。
  • initMethodName : bean初始化时要执行的方法
  • destoryMethodName : bean销毁时要执行的方法

在spring中,我们通常会通过一下几种方式来定义bean

  1. 在spring的配置文件中,用bean标签来定义
  2. @Bean 在类上、方法上加注解来实现
  3. @Component ,直接在类上加@Component来定义

这些我们称为是声明式定义bean,我们还有编程式定义bean(其实就是我们自己new 一个对象,然后放到spring容器中)。
编程式定义bean:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 类似于new对象,这里是用builder去创建的对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
// 给创建的对象set值
beanDefinition.setBeanClass(User.class);
// 将new出来的对象,交给spring管理,放到spring的容器中去
context.registerBeanDefinition("user", beanDefinition);

beanDefinition接口中有一个很强大的实现类,GenericBeanDefinition,这里面有beanDefinition的全部实现。这个GenericBeanDefinition类下又有俩类:ScannedGenericBeanDefinition、AnnotatedGenericBeanDefinition。其中如果是spring中的扫描,被扫描出来的bean,创建的就是ScannedGenericBeanDefinition类型;如果是通过各种各样的beanDefinitionReader去生成的bean,就是AnnotatedGenericBeanDefinition类型。简单的说,spring创建的beanDefinition都是beanDefinition类型,但是通过创建的方式不同,底层是不同的beanDefinition实现。

当然,spring中也有其他的比较重要的实现,比如说 RootBeanDefinition(现在还比较常用,是跟合并beanDefinition有关系的),ChildBeanDefinition(spring2.5以后不怎么常用了)。

2、BeanDefinitionReader

beanDefinition读取器(beanDefinitionReader)可以将某个类转换为beanDefinition,是spring中常用的,相当于spring中的基础设置。

  • AnnotatedBeanDefinitoinReader : 可以吧某个类转换为beanDefinition,并且会解析该类的注解
  • XmlBeanDefinitionReader : 可以解析 标签,转换为beanDefinition

3、ClassPathBeanDefinitionScanner

classPathBeanDefinitoinScanner是扫描器,有点类似于beanDefinitionReader,他可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,如果扫描到com.zheng文件夹下,看到user1、user2、user3,3个类,就会把这三个类中带有@Commont注解的类,解析为一个个的beanDefinition。

4、BeanFactory

beanFactory表示bean工厂。会提供一些getBean、crateBean之类的方法。它有一个非常重要的实现类,叫:DefaultListableBeanFactory,也是非常核心的。

在这里插入图片描述
他继承了很多接口,表示它有很多功能:

  1. AliasRegistry : 支持别名功能,一个名字可以对应多个别名
  2. BeanDefinitionRegistry : 可以注册、保持、移除某个beanDefinition
  3. beanFactory : Bean工厂,可以根据某个bean的名字、别名、类型去获取某个bean对象
  4. SingletonBeanRegistry : 可以注册、获取某个单例bean
  5. SimpleAliasRegistry : 他是一个类,实现了AliasRegistry接口中定义的所有功能,支持别名功能
  6. ListableBeanFactory : 在BeanFactory的基础上,增加了其他功能,可以获取所有的beanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的bean}的映射关系
  7. HierarchicalBeanFactory : 在BeanFactory的基础上,添加了获取父BeanFactory的功能。(如果子类的beanFactory中没有的话,可以去父的beanFactory找这个对象)
  8. DefaultSingletonBeanRegistry : 它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册、获取某个单例Bean的功能。
  9. ConfigurableBeanFactory : 在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示和可以指定某个类加载器进行类的加载)、设置Spring
    EL表达式解析器(标示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该beanFactory可以进行类型转换)、可以添加BeanPostProcessor(表示该beanFactory支持bean的后置处理器),可以合并BeanDefinition,可以销毁某个bean等等功能
  10. FactoryBeanRegistrySupport : 支持了FactoryBean的功能
  11. AutowireCapableBeanFactory : 是直接继承了BeanFactory,在BeanFactory的基础上,支持在创建Bean的过程中能对Bean进行自动装配
  12. AbstractBeanFactory : 实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经已经很全面了,到那时不能自动装配和获取beanNames
  13. ConfigurableListableBeanFactory : 继承了ListableBeanFactory、AutowiredCapableBeanFactory、ConfigurableBeanFactory
  14. AbstractAutowireCapableBeanFactory : 继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能
  15. DefaultListableBeanFactory : 继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大

5、ApplicationContext

applicationContext集成了beanFactory,所以你可以简单的认为,他就是个beanFactory,毕竟它继承了beanFactory,有他的全部功能。

在这里插入图片描述

  • ListableBeanFactory : 是继承的BeanFactory,拥有父类的BeanFactory的功能(创建bean、getBean啊之类的)
  • HierarchicalBeanFactory :是继承的BeanFactory,还拥有获取beanNames的功能
  • EnvironmentCapable :可以获取运行时环境的功能(没有设置运行时环境的功能)
  • MessageSource :拥有直接进行国际化的功能
  • ApplicationEventPublisher :拥有广播事件的功能(没有添加事件发生器的功能) 事件发布器。同样也说明了,它还具有事件发布的相关功能。
  • ResourcePatternResolver : 资源加载器,可以一次性获取多个资源(文件资源等等)。直接去获取某些资源的功能。

ApplicationContext有两个比较重要的实现类:

  1. AnnotationConfigApplicationContext
  2. ClassPathXmlApplicationContext

在这里插入图片描述

  1. ConfigurableApplicationContext : 继承了ApplicationContext接口,增加了,添加时间监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能

  2. AbstractApplicationContext : 实现了ConfigurableApplicationContext接口

  3. GenericApplicationContext :继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类有一个属性(DefaultListableBeanFactory
    beanFactory)

  4. AnnotationConfigRegistry : 可以单独注册某个类为BeanDefinition(可以处理该类上的@Configuration注解,可以处理@Bean注解),同时可以扫描

  5. AnnotationConfigApplicationContext : 继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了以上的所有的功能

在这里插入图片描述
它也是继承了AbstractApplicationContext,但是相对于AnnotationConfigApplicationContext而言,功能没有AnnotationConfigApplicationContext强大,比如不能注册beanDefinition。

怎么获取一个ApplicationConext

方式1:(亲测可用) 实现了ApplicationContextAware

package com.zheng.entity;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author: ztl
 * @date: 2024/05/14 22:29
 * @desc:
 */
@Component
public class TestApplicationContext implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{
        this.applicationContext = applicationContext;
    }

    public void test(){
        applicationContext.publishEvent("123");
        System.out.println("TestApplicationContext publishEvent start ");
    }
}

方式2:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Integer id;

    private String name;

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//        context.publishEvent("222");

        TestApplicationContext testApplicationContext = (TestApplicationContext) context.getBean("TestApplicationContext");
        testApplicationContext.test();;
    }
}

6、MessageSource

国际化,其实就是说能选择语言。有点类似于 applicatoin-pro.properties 中的pro一样。定义一个MessageSource可以在任意想要进行国际化的地方使用这个MessageSource

7、事件发布

定义一个时间监听器(有点类似于mq的消费者,不过不用指定名字、队列之类的)

@Bean
public ApplicationListener applicationListener() {
 return new ApplicationListener() {
  @Override
  public void onApplicationEvent(ApplicationEvent event) {
   System.out.println("接收到了一个事件");
  }
 };
}

在去发布事件:ApplicationContext context; context.publishEvent(“kkk”);
在这里插入图片描述

8、类型转换

在spring源码中,有可能需要把String转成其他类型,所以在spring源码中提供了一些技术来更方便的做对象类型的转换,关于类型转换的应用场景,后续看源码的过程中会遇到很多。

8.1、PropertyEditor (jdk提供的)

这其实是JDK提供的类型转换工具类。
如图所示,比如我想把@Value里面的值,赋值给user中的某个属性,怎么实现。
在这里插入图片描述
步骤很简单,1、定义一个转换的方式,2、将这个转换方式,放到spring中管理

  1. 转换方式 (PropertyEditor)
package com.zheng.entity;

import java.beans.PropertyEditor;
import java.beans.PropertyEditorSupport;

/**
 * @author: ztl
 * @date: 2024/05/14 22:26
 * @desc:
 */
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {

    @Override
    public void setAsText(String text) throws IllegalAccessError{
        User user = new User();
        user.setName(text);
        this.setValue(user);
    }
}
  1. 交给spring管理 (CustomEditorConfigurer)。
    在Spring源码中,如果发现当前对象是String,而需要的类型是User,就会使用该PropertyEditor来做类型转化
package com.zheng.config;

import com.zheng.entity.StringToUserPropertyEditor;
import com.zheng.entity.User;
import org.springframework.beans.factory.config.CustomEditorConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.beans.PropertyEditor;
import java.util.HashMap;
import java.util.Map;

/**
 1. @author: ztl
 2. @date: 2024/05/14 22:34
 3. @desc: 因为user是我们自定义的类,spring肯定不知道怎么把@Vaule转换为user,
 4. 所以需要我们自己提供一个转换方法。然后把这个转换方法,交给spring管理
 5. 
 */
@Component
public class TestSpringConfig {

    @Bean
    public CustomEditorConfigurer customEditorConfigurer(){
        CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
        Map<Class<?>,Class< ? extends PropertyEditor>> propertyEditorMap = new HashMap<>();

        // 所有是User类型的,都用这个StringToUserPropertyEditor来转换
        // 在Spring源码中,如果发现当前对象是String,而需要的类型是User,就会使用该PropertyEditor来做类型转化
        propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);
        customEditorConfigurer.setCustomEditors(propertyEditorMap);
        return customEditorConfigurer;
    }
}

8.2、ConversionService (spring提供的)

conversionService是spring中提供的类型转换服务,它比PropertyEditor更加强大。

  1. 提供一个转换类 (ConditionalGenericConverter)
import com.zheng.entity.User;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;

import java.util.Collections;
import java.util.Set;

/**
 1. @author: ztl
 2. @date: 2024/05/16 22:14
 3. @desc: spring中提供的类型转换。
 */
public class StringToUserConverter implements ConditionalGenericConverter {

    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        // 指定一下,要把什么类型,转换为什么类型。这里是把string转换为user。只有类型匹配的时候,才会走这个转换
        return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
    }

    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        // 将上面的String、User俩类型传进去
        return Collections.singleton(new ConvertiblePair(String.class, User.class));
    }

    /**
     * 具体的转换逻辑,这里是把string类型,传给了user中的name属性
     * @param source
     * @param sourceType
     * @param targetType
     * @return
     */
    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        User user = new User();
        user.setName((String)source);
        return user;
    }
}
  1. 将转换类交给spring管理 (ConversionServiceFactoryBean)
@Component
public class ImportBean {

    @Bean
    public ConversionServiceFactoryBean conversionService(){
        ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
        // 将我们自定义的转换类,set进来
        conversionServiceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));

        return conversionServiceFactoryBean;
    }
}

8.3、TypeConverter

整合了PropertyEditor(jdk方式)和ConversionService(spring方式)的功能,是spring内部用的。我们从上面代码中也可以看到:
PropertyEditor 是用的 CustomEditorConfigurer
ConversionService 是用的 ConversionServiceFactoryBean
那如果用不同的转换方式(jdk、spring),还要用不同的添加方式(CustomEditorConfigurer、ConversionServiceFactoryBean)去添加到spring中,那肯定不够方便。因此,spring就提供了一个方式,可以同时添加这两种-jdk、spring的。就是这个TypeConverter。

    SimpleTypeConverter typeConverter = new SimpleTypeConverter();
        typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
//        typeConverter.setConversionService(conversionService);
        // 这行是去转换的
        User value = typeConverter.convertIfNecessary("1", User.class);
        System.out.println(value);

9、OrderComparator

OrderComparator是spring所提供的一种比较器,可以用来根据@Order注解或实现了Ordered接口来执行值进行比较,从而可以进行排序。
OrderComparator是Ordered接口的比较器,还有AnnotationAwareOrderComparator,它支持用@Order来指定order值。

9.1使用Ordered接口来实现:

类1:

package com.zheng.testSpring.排序;

import org.springframework.core.Ordered;

/**
 * @author: ztl
 * @date: 2024/05/19 22:25
 * @desc: 实现了Ordered接口的类1
 */
public class InterfaceTest1 implements Ordered {
    @Override
    public int getOrder() {
        return 11;
    }

    @Override
    public String toString() {
        return "InterfaceTest1{}";
    }
}

类2

package com.zheng.testSpring.排序;

import org.springframework.core.Ordered;

/**
 * @author: ztl
 * @date: 2024/05/19 22:25
 * @desc: 实现了Ordered接口的类1
 */
public class InterfaceTest2 implements Ordered  {
    @Override
    public int getOrder() {
        return 2;
    }

    @Override
    public String toString() {
        return "InterfaceTest2{}";
    }
}

测试类: OrderComparator 来比较,

package com.zheng.testSpring.排序;

import org.springframework.core.OrderComparator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author: ztl
 * @date: 2024/05/19 22:28
 * @desc:
 */
public class InterfaceTest {

    public static void main(String[] args) {
        InterfaceTest1 test1 = new InterfaceTest1();
        InterfaceTest2 test2 = new InterfaceTest2();

        OrderComparator comparator = new OrderComparator();
        List list = new ArrayList();
        list.add(test1);
        list.add(test2);


        System.out.println(list);
//        Collections.sort(list,comparator);
        list.sort(comparator);
        System.out.println(list);

    }
}

2.用@Order来实现
类1:

package com.zheng.testSpring.排序;

import org.springframework.core.annotation.Order;

/**
 * @author: ztl
 * @date: 2024/05/19 22:35
 * @desc:
 */
@Order(11)
public class AnnotationTest1 {
    @Override
    public String toString() {
        return "AnnotationTest1{}";
    }
}

类2:

package com.zheng.testSpring.排序;

import org.springframework.core.annotation.Order;

/**
 * @author: ztl
 * @date: 2024/05/19 22:35
 * @desc:
 */
@Order(2)
public class AnnotationTest2 {
    @Override
    public String toString() {
        return "AnnotationTest2{}";
    }
}

测试类: AnnotationAwareOrderComparator来比较。

package com.zheng.testSpring.排序;

import org.springframework.core.annotation.AnnotationAwareOrderComparator;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: ztl
 * @date: 2024/05/19 22:36
 * @desc:
 */
public class AnnotationTest {

    public static void main(String[] args) {
        AnnotationTest1 test1 = new AnnotationTest1();
        AnnotationTest2 test2 = new AnnotationTest2();

        AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
        List list = new ArrayList();
        list.add(test1);
        list.add(test2);

        System.out.println(list);

        list.sort(comparator);
        System.out.println(list);
    }
}

10、MetadataReader、ClassMetadata、AnnotationMetadata

  1. MetadataReader元数据读取器,元数据可以理解为类,简单的说就是,解析一个类,得到这个类的元数据(classMetadata)。有点类似于BeanDefinition,但是beanDefinition只需要看类上面的注解(@Component、@Service之类的),看你是怎么定义这个bean的。但是MetadataReader元数据是把这个类的全部信息都给搞到手(比如类的名字、匿名内部类。是不是接口。。。)。这个元数据,也是很重要的一个类。
    具体可以看3下面的代码
    • AnnotationMetadata。hasAnnotation 这个类,本身有啥注解,不包含注解的注解。(比如@Service,他就只有service。)
    • AnnotationMetadata。hasMetaAnnotation 这个类,本身有啥注解和注解的注解。(比如@Service,他有@service、Target、Retention、@Component。。等等)
  2. classMetadata,类的元数据:可以用来读取类的名字、方法、父类、继承的类、实现的接口、匿名内部类、这个类是不是接口,是不是抽象的,是不是finial修饰的,,,等等获取类的信息
    在这里插入图片描述
  3. AnnotationMetadata。注解的元数据,这个类上有哪些注解。这里也不是只说类头那块的注解。类里面的方法里面有注解,也能给扫描出来。比如说@bean,@Autowired这些。AnnotationMetadata里面有方法(hasMetaAnnotation)可以判断,某个类(比如说user)中有没有某个注解(比如说@Bean)修饰的方法。
package com.zheng.testSpring.元数据;

import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.io.IOException;

/**
 * @author: ztl
 * @date: 2024/05/20 22:40
 * @desc:
 */
public class Test {

    public static void main(String[] args) throws IOException {
        SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
        // 构造一个MetadataReader
        MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.zheng.controller.UserController");

        // 得到这个类的元数据    ClassMetadata,并获取了类名
        ClassMetadata classMetadata = metadataReader.getClassMetadata();

        // com.zheng.controller.UserController
        System.out.println(classMetadata.getClassName());
        // 拿到这个类的父类的名字      java.lang.Object
        System.out.println(classMetadata.getSuperClassName());
        // 拿到这个类的接口的名字
        System.out.println(classMetadata.getInterfaceNames());
        // 这个类的内部类      com.zheng.controller.UserController$person
        System.out.println(classMetadata.getMemberClassNames()[0]);

        System.out.println("=========================");
        // 根据元数据,拿到这个类的注解
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        for (String annotationType : annotationMetadata.getAnnotationTypes()) {
            //org.springframework.web.bind.annotation.RestController
            //org.springframework.core.annotation.Order
            System.out.println(annotationType);
        }

        // 在我类上有@Service,没有@Component的时候,是false
        System.out.println(annotationMetadata.hasAnnotation(org.springframework.stereotype.Component.class.getName()));
        // 在我类上有@Service,没有@Component的时候,是true。说明hasMetaAnnotation会把类的注解、注解的注解,一级一级的都扫描出来
        System.out.println(annotationMetadata.hasMetaAnnotation(org.springframework.stereotype.Component.class.getName()));
    }
}

13、ExcludeFilter和IncludeFilter

这两个Filter是spring扫描的过程中用来过滤的。ExcludeFilter表示排除过滤器;IncludeFilter表示包含过滤器。

  1. excludeFilter代码: 即使你的userService上面有@Component注解,那么spring也会把这个类给排除掉。
    excludeFilters.type:可以指定注解、aspect的表达式、某个类,type如果是注解,classes就写对应的注解,如果是类,就是对应的类,如果是表达式,就是对应的表达式,就是根据type,来写的classes
@ComponentScan(value = "com.zheng",
        excludeFilters = {@ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = UserService.class)})
public class App {
}

@Service
public class  UserService {
    
}
  1. includeFilter代码: 这样的话,即使你的UserService是没有加@Component注解,spring也是可以扫描出来这个类的
@ComponentScan(value = "com.zheng",
        includeFilters = {@ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = UserService.class)})
public class UserTest2 {
}


public class  UserService {
    
}

14、FactoryBean

factoryBean有点特殊,如果你是在factoryBean上面加了@Component注解的话,返回的可能不是这个factoryBean,而是这个getObject返回的对象。

他的原理是,spring中有两个bean对象,一个是ZhengFactoryBean本身(在spring的单例池中),一个是他返回的类型OrderService(在spring的beanFactory的Map中,key是对应的factory,本次是ZhengFactoryBean,v是OrderService)。

那像这种beanFactory和直接@Bean创建出来的对象,有啥区别呢?
区别就是,beanFacotry创建出来的userService只有后置方法,而@Bean创建出来的既有前置方法,又有后置方法。别的都一样。

package com.zheng.testSpring.工厂;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

/**
 * @author: ztl
 * @date: 2024/05/22 22:53
 * @desc: 测试一下,即使加了@Component,返回的对象也不是它本身
 */

// 别看你是在ZhengFactoryBean上面加的@Component,当你从spring中获取的时候,返回的是OrderService
@Component
public class ZhengFactoryBean implements FactoryBean {
    /**
     * 这个对象返回的是什么类型,当你从spring容器中get的时候,就是什么类型
     * @return
     * @throws Exception
     */
    @Override
    public Object getObject() throws Exception {
        OrderService userService = new OrderService();

        return userService;
    }

    /**
     * 注意,getObjectType的这个class得跟getObject返回的对象类型一致。不一致会报错
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return OrderService.class;
    }
}

测试类:

package com.zheng.testSpring.工厂;

import com.zheng.TransDemoApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author: ztl
 * @date: 2024/05/22 22:58
 * @desc:
 */
public class Test {

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

        // 返回的并不是ZhengFactoryBean对象,而是OrderService对象
        System.out.println(context.getBean("ZhengFactoryBean"));
    }
}

15、BeanPostProcessor

beanPostProcessor是spring扫描完以后,依赖注入完了以后,在对象初始化的前、后做的一些强化处理的操作。aop 的底层原理就是它。这里我多说一句,BeanPostProcessor几乎可以说是spring中最重要最核心的了。一定要重视起来。一个BeanPostProcessor可以在任意一个bean的初始化前以及初始化后去额外的做一些用户自定义的逻辑,当然,我们可以通过判断beanName来进行针对性的处理(针对某一个bean或者部分Bean)

代码:(可以看手写spring的git项目,那里面的beanPostProcessor做的强化多。)

package com.zheng.testSpring.aop原理;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @author: ztl
 * @date: 2024/05/22 23:11
 * @desc:
 */
public class ZhengBeanPostProcessor implements BeanPostProcessor {
    // 初始化前的操作
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("userService".equals(beanName)){
            System.out.println("初始化前的操作");
        }
        return bean;
    }

    // 初始化后的操作
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("userService".equals(beanName)){
            System.out.println("初始化前的操作");
        }
        return bean;
    }
}

手写spring中的强化:

package com.testspring.service;

import com.handspring.MyBeanPostProcessor;
import com.handspring.MyComponent;
import com.testspring.ZhengValue;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author: ztl
 * @date: 2024/05/07 22:38
 * @desc: 写一个类,去实现我自己定义的,类似于spring中的  beanPostProcessor 的类
 *  todo: 注意,beanPostProcessor 非常重要,几乎是spring中最重要的了。
 *          像aop、依赖注入,几乎底层都是他
 *              aop 原理
 */

@MyComponent
public class ZtlMyBeanPostProcessor implements MyBeanPostProcessor {

    /**
     * 做前置操作
     * @param bean      要操作的对象
     * @param beanName  要操作的bean的,beanName
     * @return
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws IllegalAccessException {
        // 操作属性赋值-实现beanNameAware的回调功能
        for (Field field : bean.getClass().getDeclaredFields()){
            if (field.isAnnotationPresent(ZhengValue.class)){
                field.setAccessible(true);
                // 赋值,赋什么值呢,我们自定义注解中的value值
                field.set(bean,field.getAnnotation(ZhengValue.class).value());
            }
        }


        // 你在这,也可以针对某一个key做处理,比如说我只想对userService做处理
        if ("userServiceAop".equals(beanName)){
            System.out.println("注意注意注意,aop原理-我执行了beanPostProcessor的前置操作");
            // 类加载器 ; 当前类有那些接口,我就代理哪些接口 ;具体的代理逻辑
            Object proxyInstance = Proxy.newProxyInstance(ZtlMyBeanPostProcessor.class.getClassLoader(),
                    bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    // 执行的切面逻辑:
                    System.out.println("我执行了具体的切面逻辑--aop");

                    // 注意,这里的对象传的是原始的bean对象(userService),而不是传代理对象(userService的代理类)
                    return method.invoke(bean,args);
                }
            });

            // 返回我的代理对象
            return proxyInstance;
        }

        return bean;


    }

}

总结

看起来确实比较枯燥。不过我们自己写demo尝试的时候,还是很有成就感的。毕竟是操作spring的各种入口来实现自己的逻辑,瞬间高大上了不少。在这里也是为了方便自己后续的查阅。

  • 29
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值