回顾
Bean的生命周期流程图
包扫描流程图
当前BeanDefinition对应的类被成功加载之后,就可以进行实例化对象了.
但是在Spring中,实例化对象前,Spring提供了一个扩展点,允许用户来控制是否在某个或者某些Bean实例化前做一些启动动作.
这个扩展点叫InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
需要注意的是这里是有返回值的,如果实现了这个并且返回了一个对象,那么后续Spring的依赖注入也就不会进行了,会跳过一些步骤,直接进行初始化后这一步.
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
...
}
在这一步就会根据BeanDefinition去创建一个对象了.
首先判断BeanDefinition是否设置了Supplier,如果设置了就会调用Supplier#get()得到对象.
@Test
public void testSupplier() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
bd.setInstanceSupplier(UserService::new);
ctx.registerBeanDefinition("userService", bd);
UserService userService = ctx.getBean("userService", UserService.class);
userService.test();
}
如果没有设置Supplier,就会检查BeanDefinition是否设置了factoryMethod,也就是工厂方法,有两种方式可以设置factoryMethod
方法一
<bean id="userService" class="linc.cool.service.UserService" factory-method="createMethod" />
对应的类
public class UserService{
public void test() {
System.out.println(this.getClass().getName() + ".test()");
}
public static UserService createMethod() {
System.out.println("执行createUserService()");
return new UserService();
}
}
方式二
<bean id="commonService" class="linc.cool.service.CommonService"/>
<bean id="userService" factory-bean="commonService" factory-method="createUserService"/>
对应的CommonService
public class CommonService {
public UserService createUserService() {
return new UserService();
}
}
Spring发现当前BeanDefinition方法设置了工厂方法后,就会区分这两种方式,然后调用工厂方法得到对象
注意的是,我们通过@Bean所定义的BeanDefinition是存在factoryMethod和factoryBean的,也就是和上面的方式二非常类似
@Bean所注解的方法就是factoryMethod,AppConfig对象就是factoryBean
如果@Bean所注解的方法是static的,那么对应的就是方式一
Spring在基于某个类生成Bean的过程中,需要利用该类的构造方法来实例化得到一个对象,但是如果一个类中存在多个构造方法,Spring的判断逻辑如下:
如果一个类只存在一个构造方法,不管这个构造方法是无参构造还是有参构造方法,Spring都会使用这个构造方法
如果一个类中存在多个构造方法
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [linc.cool.service.UserService]: No default constructor found; nested exception is java.lang.NoSuchMethodException: linc.cool.service.UserService.<init>()
Spring的设计思想是这样的
如果一个类只有一个构造方法,那么没得选择,只能用这个构造方法
如果一个类存在多个构造方法,Spring不知道如何选择,就会看是否有无参构造方法,因为无参构造方法本身表示了一种默认的意义
如果某个构造方法上加了@Autowired注解,那就表示程序员告诉Spring我采用这个构造方法进行构造,如果Spring选择了一个有参的构造方法,Spring在调用这个有参构造方法时,需要传入参数,这些参数是怎么来的呢?
Spring会根据入参的类型和入参的名字去Spring中找Bean对象,我们以单例为例,Spring会从单例池sigletonObjects中去找:
额外的,在推断构造方法逻辑中除开回去选择构造方法以及查找入参对象以外,还会去判断是否存在对应的类中是否存在使用@Lookup注解了的方法.
如果存在就会把这个方法封装为LookupOverride对象并且添加到BeanDefinition
public class LookupOverride extends MethodOverride {
@Nullable
private final String beanName;
@Nullable
private Method method;
...
}
@Lookup注解就是方法注入
@Component
public class AService {
private BService bService;
public void test() {
BService bService = createBService();
System.out.println(bService);
System.out.println(this.getClass().getName() + ".test()");
}
@Lookup
public BService createBService() {
return new BService();
}
}
Bean对象实例化出来之后,接下来就应该给对象的属性进行赋值了
在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition,可以对此事的BeanDefinition进行加工
在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)
@Component
public class AMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if ("AService".equals(beanName)) {
beanDefinition.getPropertyValues().add("BService", new BService());
}
}
}
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
...
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
...
}
在处理完BeanDefinition之后,Spring又设计了一个扩展点InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
...
}
自动注入指的是Spring的自动注入
在这个步骤中,就会处理@Autowired、@Resource、@Value等注解
也就是通过InstantiationAwareBeanPostProcessor#postProcessProperties扩展点来实现的
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
...
}
我们可以自己实现一个注入点
@Component
public class MyAutowiredInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("AService".equals(beanName)) {
Stream.of(bean.getClass().getDeclaredFields()).forEach(f -> {
if (f.isAnnotationPresent(MyAutowired.class)) {
String value = f.getAnnotation(MyAutowired.class).value();
f.setAccessible(true);
try {
f.set(bean, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
}
return pvs;
}
}
后续涉及到的有@Autowired、@Resource、@Value的底层源码
完成了属性赋值之后,Spring会执行一些回调接口
AbstractAutowireCapableBeanFactory
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
初始化前也是Spring提供的一个扩展点BeanPostProcessor#postProcessBeforeInitialization
public interface BeanPostProcessor {
/**
* 该方法在bean实例化完毕(且已经注入完毕),在afterPropertiesSet或自定义init方法执行之前
*/
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
...
}
利用初始化前,可以对进行了依赖注入的Bean进行处理
在Spring源码中:
InitDestroyAnnotationBeanPostProcessor会在初始化前这个步骤中执行@PostConstruct的方法
ApplicationContextAwareProcessor会在初始化前这个步骤中进行其他Aware的回调
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
// 执行aware方法
invokeAwareInterfaces(bean);
}
return bean;
}
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
这是Bean创建的生命周期中的最后一个步骤,也是Spring提供的一个扩展点BeanPostProcessor#postProcessAfterInitialization
可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后进行实现的,初始化后返回的对象才是最终的Bean对象
public interface BeanPostProcessor {
...
/**
* 在afterPropertiesSet或自定义init方法执行之后
*/
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}