spring笔记⑦——spring源码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_35262405/article/details/100097106

JavaConfig注册bean

在javaConfig配置spring中,有两种方式将类对象注册到spring容器当中,不包含注解和xml配置

创建AnnotationConfigApplicationContext对象时可以传递参数,参数类型为类的class对象,这是第一种方式将对象放在spring容器中

//采用注解注解配置和javaconfig
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();

同样还可以通过register方法将想要放入spring容器的对象放进去,需要注意的是注册完还需要调用refresh作刷新,否则就放不进去

//通过register这个方法可以直接注册一个对象到spring容器当中(不需要注解)
annotationConfigApplicationContext.register(UserTest.class);
annotationConfigApplicationContext.refresh();

我们找到第一方式spring的源码,可以发现这里同样调用了registerrefresh方法,所以其实spring都是通过这两个方法将对象放入容器中的

/**
 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
 * from the given annotated classes and automatically refreshing the context.
 * @param annotatedClasses one or more annotated classes,
 * e.g. {@link Configuration @Configuration} classes
 */
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	this();
	register(annotatedClasses);
	refresh();
}

register方法

经过层层调用,我们进入doRegisterBean方法,这里创建了一个AnnotatedGenericBeanDefinition对象,属于描述bean的对象,就相当于jdk中描述对象的class类对象一样。

//描述bean的对象,相当于jdk中对象与它的class类的关系
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

最后将abd和beanname放入bdh中,注意这个bdh并没有实际的意义,只是为了传值方便创造了一个容器一样,传入registerBeanDefinition方法

//将abd和beanname放入bdh中,注意这个bdh并没有实际的意义,只是为了传值方便创造了一个容器一样
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

这里执行的是DefaultListableBeanFactory的registerBeanDefinition方法
在这里插入图片描述
在这个方法中会将bean的描述和beanname以键值对的形式放入到一个map中,还把beanname单独放到一个list集合中

refresh方法

这里先重点看看prepareBeanFactory方法,传入的是bean工厂
在这里插入图片描述
前面是一些初始化工作,注意addBeanPostProcessor这个方法的作用是添加一个后置处理器,其底层实现是向list中添加元素

在这里插入图片描述
添加进去的对象是一个实现了BeanPostProcessor接口的对象,也证实了这就是一个后置处理器
在这里插入图片描述
我们可以通过实现BeanPostProcessor接口,重写其中的方法,并且将这个对象加入到spring容器中,我们也可以插手spring生成bean的过程。不过这只是扩展的方式之一。

实现后置处理器扩展bean(BeanPostProcessor)

可以看到实现了BeanPostProcessor的类有太多太多,也就是说spring自身也通过这个方式扩展bean的生产过程
在这里插入图片描述
这里实现了对UserTest对象的简单扩展,这里的方法是直接把bean传给了使用者,所以使用者可以直接对bean进行操作,这也意味着实现这个接口可以插手spring的bean实例化过程

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof UserTest){
			System.out.println("postProcessBeforeInitialization");
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof UserTest){
			System.out.println("postProcessAfterInitialization");
		}
		return bean;
	}
}
public class UserTest {

	public UserTest(){
		System.out.println("UserTest");
	}

	@PostConstruct
	public void init(){
		System.out.println("init");
	}


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

public static void main(String[] args) {
	//采用注解注解配置和javaconfig
	AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
	//通过register这个方法可以直接注册一个对象到spring容器当中(不需要注解)
	annotationConfigApplicationContext.register(UserTest.class);
	UserTest userTest = annotationConfigApplicationContext.getBean(UserTest.class);
	userTest.test();
}

结果执行的顺序如下

UserTest
postProcessBeforeInitialization
init
postProcessAfterInitialization
test

而且这种扩展的类也可以不止一个,那么就有一个顺序的问题,需要通过实现PriorityOrdered接口来排序,那么就需要实现接口的方法getOrder其中返回的值的大小就决定了这些bean的初始化顺序,越小就表示越前。

@Override
public int getOrder() {
	return 101;
}

bean的类型

  • 注解实现的bean
  • xml实现的baen
  • JavaConfig中@bean注解定义的bean
  • spring内部自己的bean

猜你喜欢

转载自blog.csdn.net/qq_35262405/article/details/100097106