提示: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
- 在spring的配置文件中,用bean标签来定义
- @Bean 在类上、方法上加注解来实现
- @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,也是非常核心的。
他继承了很多接口,表示它有很多功能:
- AliasRegistry : 支持别名功能,一个名字可以对应多个别名
- BeanDefinitionRegistry : 可以注册、保持、移除某个beanDefinition
- beanFactory : Bean工厂,可以根据某个bean的名字、别名、类型去获取某个bean对象
- SingletonBeanRegistry : 可以注册、获取某个单例bean
- SimpleAliasRegistry : 他是一个类,实现了AliasRegistry接口中定义的所有功能,支持别名功能
- ListableBeanFactory : 在BeanFactory的基础上,增加了其他功能,可以获取所有的beanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的bean}的映射关系
- HierarchicalBeanFactory : 在BeanFactory的基础上,添加了获取父BeanFactory的功能。(如果子类的beanFactory中没有的话,可以去父的beanFactory找这个对象)
- DefaultSingletonBeanRegistry : 它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册、获取某个单例Bean的功能。
- ConfigurableBeanFactory : 在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory、类加载器(表示和可以指定某个类加载器进行类的加载)、设置Spring
EL表达式解析器(标示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示该beanFactory可以进行类型转换)、可以添加BeanPostProcessor(表示该beanFactory支持bean的后置处理器),可以合并BeanDefinition,可以销毁某个bean等等功能 - FactoryBeanRegistrySupport : 支持了FactoryBean的功能
- AutowireCapableBeanFactory : 是直接继承了BeanFactory,在BeanFactory的基础上,支持在创建Bean的过程中能对Bean进行自动装配
- AbstractBeanFactory : 实现了ConfigurableBeanFactory接口,继承了FactoryBeanRegistrySupport,这个BeanFactory的功能已经已经很全面了,到那时不能自动装配和获取beanNames
- ConfigurableListableBeanFactory : 继承了ListableBeanFactory、AutowiredCapableBeanFactory、ConfigurableBeanFactory
- AbstractAutowireCapableBeanFactory : 继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能
- DefaultListableBeanFactory : 继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大
5、ApplicationContext
applicationContext集成了beanFactory,所以你可以简单的认为,他就是个beanFactory,毕竟它继承了beanFactory,有他的全部功能。
- ListableBeanFactory : 是继承的BeanFactory,拥有父类的BeanFactory的功能(创建bean、getBean啊之类的)
- HierarchicalBeanFactory :是继承的BeanFactory,还拥有获取beanNames的功能
- EnvironmentCapable :可以获取运行时环境的功能(没有设置运行时环境的功能)
- MessageSource :拥有直接进行国际化的功能
- ApplicationEventPublisher :拥有广播事件的功能(没有添加事件发生器的功能) 事件发布器。同样也说明了,它还具有事件发布的相关功能。
- ResourcePatternResolver : 资源加载器,可以一次性获取多个资源(文件资源等等)。直接去获取某些资源的功能。
ApplicationContext有两个比较重要的实现类:
- AnnotationConfigApplicationContext
- ClassPathXmlApplicationContext
-
ConfigurableApplicationContext : 继承了ApplicationContext接口,增加了,添加时间监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能
-
AbstractApplicationContext : 实现了ConfigurableApplicationContext接口
-
GenericApplicationContext :继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类有一个属性(DefaultListableBeanFactory
beanFactory) -
AnnotationConfigRegistry : 可以单独注册某个类为BeanDefinition(可以处理该类上的@Configuration注解,可以处理@Bean注解),同时可以扫描
-
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中管理
- 转换方式 (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);
}
}
- 交给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更加强大。
- 提供一个转换类 (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;
}
}
- 将转换类交给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
- MetadataReader元数据读取器,元数据可以理解为类,简单的说就是,解析一个类,得到这个类的元数据(classMetadata)。有点类似于BeanDefinition,但是beanDefinition只需要看类上面的注解(@Component、@Service之类的),看你是怎么定义这个bean的。但是MetadataReader元数据是把这个类的全部信息都给搞到手(比如类的名字、匿名内部类。是不是接口。。。)。这个元数据,也是很重要的一个类。
具体可以看3下面的代码- AnnotationMetadata。hasAnnotation 这个类,本身有啥注解,不包含注解的注解。(比如@Service,他就只有service。)
- AnnotationMetadata。hasMetaAnnotation 这个类,本身有啥注解和注解的注解。(比如@Service,他有@service、Target、Retention、@Component。。等等)
- classMetadata,类的元数据:可以用来读取类的名字、方法、父类、继承的类、实现的接口、匿名内部类、这个类是不是接口,是不是抽象的,是不是finial修饰的,,,等等获取类的信息
- 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表示包含过滤器。
- 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 {
}
- 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的各种入口来实现自己的逻辑,瞬间高大上了不少。在这里也是为了方便自己后续的查阅。