Spring之核心概念与手写简单框架

前言

更新了一些java基础文章后,我发现文章的阅读量偏低啊,我就在想是不是一些基础的东西大家都是会的,或者大家在工作中不需要了解太多源码实现的东西。。最后想着那就连着java基础和工作中常用框架的讲解一起更新吧!
在工作中大家只要是写java web应用,相信都离不开Spring框架。那么大家对Spring框架底层是否有一些深刻的了解呢?接下来这一篇文章就带大家了解一下Spring框架核心概念并通过手写简单框架来加深大家的印象,为后续的源码阅读打下基础。这一章超级长,请耐心阅读或选择性阅读。

请添加图片描述


核心流程

首先我们通过几个问题与简易的回答来了解一下Spring底层的流程。

Spring如何创建一个对象

在Spring中最重要的一个类就是ApplicationContext,它的实现类有以下几种。

对.xml进行解析的 ClassPathXmlApplicationContext
接收一个配置类进行解析的 AnnotationConfigApplicationContext
MVC框架中的XmlWebApplicationContext与AnnotationConfigWebApplicationContext等

然后我们通过一个例子看一下如何快速使用Spring并拿到一个bean。

AnnotationConfigApplicationContext context = 
new AnnotationConfigApplicationContext(AppConfig.class);

UserService service = (UserService) context.getBean("userServiceImpl");
service.test();

我们可以看到通过getBean()并传入一个名称就获取到了一个bean,说明上面一个语句里面创建了这个bean,并且可能用了一个Map映射名称与bean的关系。(当然这里不是很严谨,getBean()也可能会创建bean,这个后面详细讲。)在调用new AnnotationConfigApplicationContext(AppConfig.class);会做以下一些事情。

  1. 解析AppConfig.class得到扫描路径
  2. 根据扫描路径加载所有java类,如果有@Component等注解就记录到一个Map中,先简单理解为Map<String, Class>
  3. 其中String-名称会按规则生成beanName,然后根据记录的Class生成Bean再存入一个Map中<String, Object>

当然上面的步骤描述在源码中实现的更加复杂,并且还有很多其他的逻辑实现,比如在解析AppConfig.class之前会加载扫描器、运行环境等信息。作为前置铺垫知识我们先简单理解即可。


Bean创建过程

接下来我们再深入一点看一下Spring如何来创建一个Bean,即Bean的生命周期。

  1. 首先会根据构造方法进行实例化,如果有多个构造方法就需要根据规则去推断构造方法,选择一个。
  2. 得到一个对象后,Spring会查看类里面的组成字段是否有注解例@Autowired,然后根据规则对字段进行属性注入,例private UserService userService上标注@Autowired会往这个字段注入UserService。
  3. 查看Bean是否实现BeanNameAware等接口,如果实现了Spring就会回调这些接口中的特定方法并传入特定的值供用户使用。例BeanNameAware定义了setBeanName()的方法,用户可以实现这个方法并得到当前Bean名字。
  4. Aware回调后,Spring会查看对象中的方法是否有@PostConstruct注解,如果有就会调用此方法。
  5. 然后Spring判断是否实现了InitializingBean接口,如果实现了就会调用afterPropertiesSet()方法
  6. 最后Spring判断当前Bean是否需要进行AOP,如果不需要就创建完成,如果需要就进行代理并返回代理对象。

当Bean创建完后:

  1. 如果是单例Bean会存入一个Map中<String, Object>,下一次如果还是要这个Bean就会直接在Map中获取
  2. 如果是远行Bean就不会存入Map中,下一次拿Bean会重新执行创建Bean的逻辑。

推断构造方法

一个类中可能存在多个构造方法,那么Spring需要根据用户的配置选择进行实例化这个类,那么就需要一些规则供用户配置。
Spring推断构造方法设计思想:

  1. 如果只有一个构造方法就选择这一个。
  2. 如果有多个构造方法,那么Spring会查看里面是否有一个无参的构造方法,如果有就选择它,没有就会报错。
  3. 如果某个构造方法上有@Autowired注解,那么就选择这一个
  4. 如果多个构造方法都标识@Autowired注解并且都没有使用配置@Autowired(required=false),报错。
  5. 如果多个构造方法都标识@Autowired注解并且只有一个为@Autowired或@Autowired(required=true)就会选择这一个。

如果最后Spring选择了一个有参数的构造方法就会根据它的类型与名称去Spring中找这个Bean并进行注入,如果有没找到会报错。


AOP简述

AOP就是对一个Bean的动态代理,在Bean的生命周期最后会判断Bean是否需要AOP。那么如何判断是否需要AOP呢?

  1. 找到所有切面Bean
  2. 遍历所有切面的方法,是否标注@before等注解
  3. 根据注解的表达式判断当前Bean符合条件
  4. 如果符合就根据这个方法进行AOP

利用cglib进行AOP流程:

  1. 生成代理类UserServiceProxy,继承于UserService
  2. 代理类重写父类方法,代理类中target属性表示UserService,即被代理类
  3. 返回的对象为UserServiceProxy,如果调用UserService中被代理方法例print(),就会执行切面逻辑并执行target.print()

简单理解:
UserService userService = UserServiceProxy; 因为UserServiceProxy继承于UserService所以可以赋值。
userService.print()即是UserServiceProxy.print() ->切面逻辑(假如这里只有@before)->target.print()


Spring事务

Spring会判断方法是否存在@Transactional注解,如果存在会开启Spring事务,那么我们调用的那个类就是当前Bean对象的代理类。
我们先梳理一下步骤:

  1. 判断方法是否有@Transactional注解
  2. 存在,启用事务管理器建立数据库连接,关闭自动提交
  3. 执行业务,正常提交,失败回滚

那么这些步骤要怎么在原方法中插进去呢?如果这是一段切面逻辑就可以了,在执行方法前开启事务,在执行方法后判断回滚。

try{
 // 业务
} catch(...) {
	// rollback
}
.....

所以要判断@Transactional方法是否正常开启了事务,就要判断是否是代理方法进行的方法调用。


核心概念

了解了一些大概的流程之后,我们就深入流程中讲一些重要的概念,为后面的Spring详细源码打一些基础。


BeanDefinition

在获取到AppConfig.class配置的扫描路径后,Spring按照这个路径扫描java类并判断是否是一个Bean,如果是就会将名字作为Key,Bean的描述作为Value存储到一个Map中,这个描述就是BeanDefinition。
BeanDefinition描述了许多Bean的特点:

  1. class:Bean类型
  2. scope:Bean的作用域,单例之类的
  3. lazyInit: 是否懒加载
  4. dependsOn Bean依赖于 等。。

那么我们怎么声明一个BeanDefinition呢?

  1. <bean/>
  2. @Bean
  3. @Component等

那么除了以上的声明式还有一下的编程式:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();

beanDefinition.setBeanClass(BService.class);
context.registerBeanDefinition("bService", beanDefinition);

BeanDefinitionReader

如名称,可以读取类并解析为BeanDefinition,根据不同的Bean配置方法有不同的查找注册方式。

  • AnnotatedBeanDefinitionReader,解析传入类的以下注解并生成BeanDefinition
    @Conditional,@Scope、@Lazy、@Primary、@DependsOn、 @Role、@Description
  • XmlBeanDefinitionReader,解析xml
  • ClassPathBeanDefinitionScanner,它其实是一个扫描器,用来扫描包路径并进行类解析。

BeanFactory

如名称,它是一个Bean工厂,负责创建获取Bean等一系列操作。
请添加图片描述
而在实现类有很多,例如我们非常熟悉的ApplicationContext,而在这些实现类中有一个非常重要的实现类DefaultListableBeanFactory

首先我们来看一下DefaultListableBeanFactory的实现结构图。
请添加图片描述

然后我们来看一下实现接口和类的一些功能:

  1. AliasRegistry:别名功能
  2. BeanDefinitionRegistry:注册、查询、移除BeanDefinition
  3. BeanFactory:创建、查询、获取Bean(名称、类型)、查询别名
  4. SingletonBeanRegistry:注册获取单例Bean
  5. SimpleAliasRegistry:实现了AliasRegistry接口的功能
  6. ListableBeanFactory:在BeanFactory的基础上添加根据类型、注解获取BeanName,根据类型获取对应Bean,获取所有BeanDefinition的name
  7. HierarchicalBeanFactory:在BeanFactory的基础上添加父BeanFactory功能
  8. DefaultSingletonBeanRegistry:实现了SingletonBeanRegistry并继承了SimpleAliasRegistry
  9. ConfigurableBeanFactory:在继承类的基础上多了添加Bean后置处理器、解析SPEL表达式、类型转换、销毁Bean、获取类加载器等。
  10. FactoryBeanRegistrySupport:拥有 FactoryBean 功能。
  11. AutowireCapableBeanFactory:在BeanFactory基础上增加autowired注入装配Bean功能
  12. AbstractBeanFactory:实现ConfigurableBeanFactory并继承FactoryBeanRegistrySupport,但无法获取BeanName与自动装配
  13. ConfigurableListableBeanFactory:继承了ListableBeanFactory、 AutowireCapableBeanFactory、ConfigurableBeanFactory
  14. AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了 AutowireCapableBeanFactory,拥有了自动装配的功能
  15. DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了 ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,看到这里就知道了DefaultListableBeanFactory的功能超级强大

请添加图片描述


ApplicationContext

ApplicationContext是接口,有很多的实现,在看具体实现前我们先看一下这个接口的继承情况吧。

  1. EnvironmentCapable:获取运行环境
  2. ListableBeanFactory:拥有获取beanNames的功能
  3. HierarchicalBeanFactory: 获取父BeanBeanFactory
  4. MessageSource:国际化
  5. ApplicationEventPublisher 事件发布器
  6. ResourcePatternResolver:资源加载器,可以一次性获取多个资源

然后我们看一下两个比较重要的实现类。


AnnotationConfigApplicationContext

我们直接看关系图。

请添加图片描述

  1. ConfigurableApplicationContext:添加事件监听器,BeanFactory后置处理器,设置环境等功能
  2. AbstractApplicationContext:实现了ConfigurableApplicationContext接口
  3. GenericApplicationContext:继承了AbstractApplicationContext,实现了 BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册 BeanDefinition,注意这个类中有一个属性(DefaultListableBeanFactory beanFactory)
  4. AnnotationConfigRegistry:注册配置类与扫描类包的功能
  5. AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了 AnnotationConfigRegistry接口,拥有了以上所有的功能

ClassPathXmlApplicationContext

没有AnnotationConfigApplicationContext的功能强大。
请添加图片描述


类型转换

类型转换有JDK本身提供的实现和Spring提供的实现,但是功能都是转换类型罢了,那么Spring就需要兼容这两种方式。


PropertyEditor

JDK提供的方式

public class String2User extends PropertyEditorSupport {

	@Override
	public void setAsText(String text) throws IllegalArgumentException {
		User user = new User();
		user.setName(text);
		this.setValue(user);
	}
}

public class Test {
	public static void main(String[] args) {

		String2User propertyEditor = new String2User();
		propertyEditor.setAsText("66778");
		User user = (User) propertyEditor.getValue();
		System.out.println(user);
	}
}

注册到Spring中

@Bean
	public CustomEditorConfigurer customEditorConfigurer() {
		CustomEditorConfigurer configurer = new CustomEditorConfigurer();
		Map<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap 
		= new HashMap<>();
		
		propertyEditorMap.put(User.class, String2User.class);
		configurer.setCustomEditors(propertyEditorMap); 
		
		return configurer;
	}

ConversionService

Spring提供

public class String2UserConvert implements ConditionalGenericConverter {


	@Override
	public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
		return sourceType.getType().equals(String.class)
				&& targetType.getType().equals(User.class);
	}

	@Override
	public Set<ConvertiblePair> getConvertibleTypes() {
		return Collections.singleton(new ConvertiblePair(String.class, User.class));
	}

	@Override
	public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
		String s = (String) source;
		if (!StringUtils.isEmpty(s)) {
			User user = new User();
			user.setName(s);
			return user;
		}
		return null;
	}
}

public class Test {

	public static void main(String[] args) {

		DefaultConversionService conversionService = new DefaultConversionService();
		conversionService.addConverter(new String2UserConvert());
		
		User user = conversionService.convert("66778", User.class);
		System.out.println(user);
	}
}

向Spring注册

@Bean public ConversionServiceFactoryBean conversionService() { 
	ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean(); 
	conversionServiceFactoryBean.setConverters
	(Collections.singleton(new StringToUserConverter())); 
	return conversionServiceFactoryBean; 
}

TypeConverter

整合了PropertyEditor和ConversionService的功能,适配两个方式,Spring内部使用。


OrderComparator

OrderComparator是Spring所提供的一种比较器,可以用来根据@Order注解或实现Ordered接口设置值进行比较。

AnnotationAwareOrderComparator comparator = 
new AnnotationAwareOrderComparator(); 

comparator.compare(a, b);

其中a与b是两个标注了@Order注解的类

OrderComparator comparator = new OrderComparator(); 
comparator.compare(a, b);

而这上面的a与b是实现了Ordered接口的类


BeanPostProcessor

BeanPostProcess表示Bena的后置处理器,我们可以定义一个或多个BeanPostProcessor。

@Component
public class AServiceBeanPostProcesser implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, 
	String beanName) throws BeansException {
		System.out.println("所有类都会打印>>>初始化前");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, 
	String beanName) throws BeansException {
		if ("aService".equals(beanName)) {
			System.out.println("只有AService才会打印>>>初始化后");
		}
		return bean;
	}
}

注意要加上@Component,这样Spring才会把它当成组件加载,这样每一个Bean进行初始化前后都会调用到这个BeanPostProcesser。在这些方法中可以干涉Spring创建流程。


BeanFactoryPostProcessor

BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似, BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。

@Component
public class ABeanFactoryPostProcesser implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
		AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
		definition.setBeanClass(User.class);
		definition.setLazyInit(true);
		registry.registerBeanDefinition("user1", definition);
	}
}

在上面的例子中直接注册类一个名为user1的User BeanDefinition。


FactoryBean

由我们自己来创造Bean

@Component
public class TestFactoryBean implements FactoryBean {


	@Override
	public Object getObject() throws Exception {
		User user = new User();
		user.setName("三木易不爱卷");
		return user;
	}

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

// 然后我们去拿到这个类看一下返回的是什么
AnnotationConfigApplicationContext context = 
new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(context.getBean("testFactoryBean"));

// 返回了User
User{id=null, Name='三木易不爱卷'}

通过上面这段代码,我们自己创造了一个User对象,并且它将成为Bean。但是通过这种方式 创造出来的User的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比如依赖注入。


ExcludeFilter和IncludeFilter

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

@ComponentScan(value = "com.malongmall", 
includeFilters = {@ComponentScan.Filter(
type = FilterType.CUSTOM, classes = ProcesserChainScanner.class)},
excludeFilters = {})

FilterType分为:

  1. ANNOTATION:表示是否包含某个注解
  2. ASSIGNABLE_TYPE:表示是否是某个类
  3. ASPECTJ:表示否是符合某个Aspectj表达式
  4. REGEX:表示是否符合某个正则表达式
  5. CUSTOM:自定义

MetadataReader、ClassMetadata、 AnnotationMetadata

在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。

需要注意的是,SimpleMetadataReader去解析类时,使用的ASM技术。
为什么要使用ASM技术,Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了ASM技术。


仿照Spring实现简单框架

我们把一些基础的概念与流程看完之后,接下来我们来实现一下Spring的扫描装载Bean简单版代码吧。
我们直接配合代码的注释来看一下详细的实现。

public class AnnotationConfigApplicationContext {

	// 记录配置类
    private Class configClass;

	// 存储组件的BeanDefinition
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap();

	// 存储Bean
    private Map<String, Object> singletonObjects = new HashMap();

	// 存储Bean的后置处理器,每一个Bean创建时都会来循环调用里面所有的处理器
    private List<BeanPostProcessor> postProcessors = new ArrayList();

	// 构造方法,传入一个配置类
    public AnnotationConfigApplicationContext(Class componentClass) {

		// 拿到配置类之后进行解析扫描
        this.configClass = componentClass;
        scan(componentClass);

		// 开始创建单例非懒加载Bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            BeanDefinition beanDefinition = entry.getValue();
            if ("singleton".equals(beanDefinition.getScope()) && !beanDefinition.isLazy()) {
            
            	// 创建完后放入Map中
                Object bean = createBean(entry.getKey(), beanDefinition);
                singletonObjects.put(entry.getKey(), bean);
            }
        }
    }

    public Object getBean(String beanName) {
    
		// 如果BeanDefinition没有就没有了,有就获取
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new NullPointerException();
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);

		// 单例就创建并放入Map中,原型直接返回,注意单例懒加载后进入if
        if (beanDefinition.getScope().equals("singleton")) {
            Object singletonBean = singletonObjects.get(beanName);
            if (singletonBean == null) {
                singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
            return singletonBean;
        } else {
            Object prototypeBean = createBean(beanName, beanDefinition);
            return prototypeBean;
        }
    }


    private Object createBean(String key, BeanDefinition beanDefinition) {
        Class clazz = beanDefinition.getClazz();
        Object bean = null;
        try {
			// 直接new出来
            bean = clazz.getConstructor().newInstance();

			// 遍历字段是否有@Autowired,简单实现:有就根据Name进行注入
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    field.set(bean, getBean(field.getName()));
                }
            };

			// aware回调
            if (BeanNameAware.class.isAssignableFrom(clazz)) {
                ((BeanNameAware)bean).setBeanName(key);
            }

			// 后置处理器的初始化前逻辑,我们这里有一个后置处理器实现了@Value注入值
            for (BeanPostProcessor postProcessor : postProcessors) {
                bean = postProcessor.postProcessBeforeInitialization(bean, key);
            }

			// 初始化接口回调
            if (InitializingBean.class.isAssignableFrom(clazz)) {
                ((InitializingBean)bean).afterPropertiesSet();
            }

			// 初始化后回调,我们这里有一个后置处理器判断如果是userServiceImpl就进行AOP
            for (BeanPostProcessor postProcessor : postProcessors) {
                bean = postProcessor.postProcessAfterInitialization(bean, key);
            }

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        
        return bean;
    }

	
    public void scan(Class componentClass) {

		// 查看配置类上是否有ComponentScan注解,有才进行扫描,我们默认都有
        ComponentScan annotation = (ComponentScan) componentClass.getAnnotation(ComponentScan.class);
        String scanPath = annotation.basePackage();

		// 将拿到的路径进行处理并进行加载
		// com/muyi
        scanPath = scanPath.replace('.','/');
        ClassLoader classLoader = AnnotationConfigApplicationContext.class.getClassLoader();
        URL resource = classLoader.getResource(scanPath);
        if (resource==null) {
            return;
        }
        File file = new File(resource.getFile());
        if (file.isDirectory()) {

			// 遍历这里路径里面所有的文件,我们默认都是java类
            for (File f : file.listFiles()) {

				// 将全路径处理成 com.muyi.UserService 这样
                String absolutePath = f.getAbsolutePath();
                String path = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"))
                        .replace("/", ".");
                try {
                	// 这里简单实现,直接加载类判断是否有Component组件
                    Class<?> clazz = classLoader.loadClass(path);
                    if (clazz.isAnnotationPresent(Component.class)) {

						// 如果是一个Bean后置处理器就直接创建对象存起来
                        if(BeanPostProcessor.class.isAssignableFrom(clazz)) {
                            BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
                            postProcessors.add(instance);
                        }

                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setClazz(clazz);
                        beanDefinition.setScope("singleton");
                        beanDefinition.setLazy(false);

						// @Component是否设置名称,设置了就设置到BeanDefinition
						// 没有就创建默认名称
                        Component anntation = clazz.getAnnotation(Component.class);
                        String beanName = anntation.name();
                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }

						// 是否设置@Scope,没有就是singleton单例
                        if (clazz.isAnnotationPresent(Scope.class)) {
                            Scope scope = clazz.getAnnotation(Scope.class);
                            beanDefinition.setScope(scope.value());
                        }

						// 是否设置@Lazy,默认为false
                        if (clazz.isAnnotationPresent(Lazy.class)) {
                            beanDefinition.setLazy(true);
                        }

						// 最后存储Map中
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }

                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

然后我们来看一下我们Bean后置处理器自定义实现了什么?

@Component
public class ValueBeanPostProcesser implements BeanPostProcessor {

    @Override
    // 这里可以看到我们实现了初始化前的方法
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
	
		// 遍历所有字段查看是否有@Value的注释,如果有就解析@Value的值并注入到字段
		// 简单实现,默认都是String
        Field[] declaredFields = bean.getClass().getDeclaredFields();
        for (Field f : declaredFields) {
            if (f.isAnnotationPresent(Value.class)) {
                Value v = f.getAnnotation(Value.class);
                f.setAccessible(true);
                try {
                    f.set(bean, v.value());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }
}

@Component
public class AopBeanPostProcesser implements BeanPostProcessor {

    @Override
    // 这里可以看到我们实现了初始化后的方法
    public Object postProcessAfterInitialization(Object bean, String beanName) {

		// 我们判断只有userServiceImpl才会进这个方法
        if ("userServiceImpl".equals(beanName)) {

			// 对UserServiceImpl做了动态代理,并返回代理对象
            Object proxyInstance = Proxy.newProxyInstance(AopBeanPostProcesser.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("aop before");
                    Object object = method.invoke(bean, args);
                    System.out.println("aop before return");
                    return object;
                }
            });

            return proxyInstance;
        }
        return bean;
    }
}

到了这里我们就简单的实现了Spring扫描装载Bean的实现,当然实现超级粗糙。这是为了让我们对Spring有一些简单的了解,后续更好的学习,也让我们知道Spring源码其实没那么难,难的是要有这种编程思维。这里简单的手写例子我们只拿了重要的一部分讲解,完整可运行源码如下:
手写简单Spring


最后

后续就是对Spring的实际源码进行讲解了,所以这一章务必掌握。

请添加图片描述

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值