ApplicationContext的初始化与销毁&Bean的生命周期&BeanPostProcessor的使用&Aware使用(四)

1.ApplicationContext的初始化以及销毁

对于BeanFactory也有一个初始化和销毁关闭的过程,比如编程式的容器如下:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainApp.class);

构造方法如下:

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        this();
        register(componentClasses);
        refresh();
    }

refresh是IoC的开始,方法如下:

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 是为启动过程做了一些准备工作,为容器配置了Classloader、PropertyEditor、BeanPostProcessor、Environment环境等信息,从而为容器启动做了必要的准备工作。

    /**
     * Configure the factory's standard context characteristics,
     * such as the context's ClassLoader and post-processors.
     * @param beanFactory the BeanFactory to configure
     */
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Register early post-processor for detecting inner beans as ApplicationListeners.
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

同时,容器在关闭时也会做一系列的操作。在doClose中,先发出容器关闭的信号、然后将Bean逐个关闭,最后关闭容器自身。org.springframework.context.support.AbstractApplicationContext#doClose:

    protected void doClose() {
        // Check whether an actual close attempt is necessary...
        if (this.active.get() && this.closed.compareAndSet(false, true)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Closing " + this);
            }

            LiveBeansView.unregisterApplicationContext(this);

            try {
                // Publish shutdown event.
                publishEvent(new ContextClosedEvent(this));
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
            }

            // Stop all Lifecycle beans, to avoid delays during individual destruction.
            if (this.lifecycleProcessor != null) {
                try {
                    this.lifecycleProcessor.onClose();
                }
                catch (Throwable ex) {
                    logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
                }
            }

            // Destroy all cached singletons in the context's BeanFactory.
            destroyBeans();

            // Close the state of this context itself.
            closeBeanFactory();

            // Let subclasses do some final clean-up if they wish...
            onClose();

            // Reset local application listeners to pre-refresh state.
            if (this.earlyApplicationListeners != null) {
                this.applicationListeners.clear();
                this.applicationListeners.addAll(this.earlyApplicationListeners);
            }

            // Switch to inactive.
            this.active.set(false);
        }
    }

2.  Bean的生命周期

容器的实现是通过IoC来管理Bean的生命周期来实现的。Spring IoC容器在对Bean的生命周期进行管理时提供了Bean生命周期的各个时间点的回调。IoC中Bean的生命周期如下:

(1)Bean实例的创建

(2)为Bean实例设置属性

(3)调用Bean的初始化方法

(4)应用可以通过IoC容器使用Bean

(5)容器关闭时,调用Bean的销毁方法

在上一节IoC依赖注入过程中研究了Bean实例的创建、设置属性、调用Bean的初始化。

(1) 实例的创建实际就是反射或者CGlib代理生成对象

(2) 设置属性实际就是依赖注入

(3) Bean的初始化方法:  依赖注入完成之后调用初始化initializeBean方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

    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);
            }
        }
    }

    protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
            throws Throwable {

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isTraceEnabled()) {
                logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) &&
                    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

-1》在调用初始化方法之前,会先调用invokeAwareMethods 一系列的ware接口实现,把相关的BeanName、BeanClassLoader以及BeanFactory注入到Bean中去。

-2》接着调用applyBeanPostProcessorsBeforeInitialization 处理BeanPostProcessor的postProcessBeforeInitialization 初始化之前逻辑。需要注意 @PostConstruct 注解声明的方法也是在这个阶段被调用的,其对应的BeanPostProcessor 是CommonAnnotationBeanPostProcessor

    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

CommonAnnotationBeanPostProcessor 处理逻辑如下:

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor继承自父类的postProcessBeforeInitialization方法

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 找到PostConstruct 声明的方法
        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        try {
            // 反射调用
            metadata.invokeInitMethods(bean, beanName);
        }
        catch (InvocationTargetException ex) {
            throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
        }
        return bean;
    }

寻找注解声明的方法如下:

    private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
        if (this.lifecycleMetadataCache == null) {
            // Happens after deserialization, during destruction...
            return buildLifecycleMetadata(clazz);
        }
        // Quick check on the concurrent map first, with minimal locking.
        LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
        if (metadata == null) {
            synchronized (this.lifecycleMetadataCache) {
                metadata = this.lifecycleMetadataCache.get(clazz);
                if (metadata == null) {
                    metadata = buildLifecycleMetadata(clazz);
                    this.lifecycleMetadataCache.put(clazz, metadata);
                }
                return metadata;
            }
        }
        return metadata;
    }

    private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
        List<LifecycleElement> initMethods = new ArrayList<>();
        List<LifecycleElement> destroyMethods = new ArrayList<>();
        Class<?> targetClass = clazz;

        do {
            final List<LifecycleElement> currInitMethods = new ArrayList<>();
            final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

            ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
                    LifecycleElement element = new LifecycleElement(method);
                    currInitMethods.add(element);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
                    }
                }
                if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
                    currDestroyMethods.add(new LifecycleElement(method));
                    if (logger.isTraceEnabled()) {
                        logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
                    }
                }
            });

            initMethods.addAll(0, currInitMethods);
            destroyMethods.addAll(currDestroyMethods);
            targetClass = targetClass.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);

        return new LifecycleMetadata(clazz, initMethods, destroyMethods);
    }

CommonAnnotationBeanPostProcessor 构造里定义了对应的注解:

    public CommonAnnotationBeanPostProcessor() {
        setOrder(Ordered.LOWEST_PRECEDENCE - 3);
        setInitAnnotationType(PostConstruct.class);
        setDestroyAnnotationType(PreDestroy.class);
        ignoreResourceType("javax.xml.ws.WebServiceContext");
    }

-3》接着调用invokeInitMethods方法,会看到启动afterPropertiesSet 的过程,当然这需要Bean实现InitializingBean 接口,对应的初始化处理可以在InitializingBean 接口的afterPropertiesSet 方法实现,同样是对Bean的一个回调。

最后还会判断是否有initMethod,如果有那么通过invokeCustomInitMethod 直接调用最终完成对Bean的初始化。

protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
            throws Throwable {

        String initMethodName = mbd.getInitMethodName();
        Assert.state(initMethodName != null, "No init method set");
        Method initMethod = (mbd.isNonPublicAccessAllowed() ?
                BeanUtils.findMethod(bean.getClass(), initMethodName) :
                ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));

        if (initMethod == null) {
            if (mbd.isEnforceInitMethod()) {
                throw new BeanDefinitionValidationException("Could not find an init method named '" +
                        initMethodName + "' on bean with name '" + beanName + "'");
            }
            else {
                if (logger.isTraceEnabled()) {
                    logger.trace("No default init method named '" + initMethodName +
                            "' found on bean with name '" + beanName + "'");
                }
                // Ignore non-existent default lifecycle methods.
                return;
            }
        }

        if (logger.isTraceEnabled()) {
            logger.trace("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
        }
        Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);

        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                ReflectionUtils.makeAccessible(methodToInvoke);
                return null;
            });
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
                        () -> methodToInvoke.invoke(bean), getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                InvocationTargetException ex = (InvocationTargetException) pae.getException();
                throw ex.getTargetException();
            }
        }
        else {
            try {
                ReflectionUtils.makeAccessible(methodToInvoke);
                methodToInvoke.invoke(bean);
            }
            catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
    }

invokeCustomInitMethod 方法调用中,首先得到Bean定义的initMethod方法,然后通过JDK的反射得到Method对象,直接调用在Bean定义中声明的初始化方法。

-4》 调用applyBeanPostProcessorsAfterInitialization 方法处理BeanPostProcessor 的postProcessAfterInitialization 代码逻辑。 需要注意PreDestroy 注解生命的会在这个里面做处理,对应的Processor是CommonAnnotationBeanPostProcessor

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

(4) IoC容器使用Bean

(5) Bean的销毁

上面容器的销毁中 destroyBeans 是销毁Bean,经过一系列的调用会调到:org.springframework.beans.factory.support.DisposableBeanAdapter#destroy

    @Override
    public void destroy() {
        if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
            for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
                processor.postProcessBeforeDestruction(this.bean, this.beanName);
            }
        }

        if (this.invokeDisposableBean) {
            if (logger.isTraceEnabled()) {
                logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
            }
            try {
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                        ((DisposableBean) this.bean).destroy();
                        return null;
                    }, this.acc);
                }
                else {
                    ((DisposableBean) this.bean).destroy();
                }
            }
            catch (Throwable ex) {
                String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
                if (logger.isDebugEnabled()) {
                    logger.warn(msg, ex);
                }
                else {
                    logger.warn(msg + ": " + ex);
                }
            }
        }

        if (this.destroyMethod != null) {
            invokeCustomDestroyMethod(this.destroyMethod);
        }
        else if (this.destroyMethodName != null) {
            Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
            if (methodToInvoke != null) {
                invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
            }
        }
    }

首先调用  postProcessBeforeDestruction,然后调用Bean的destroy方法,最后是对Bean的自定义销毁方法的调用,和前面初始化的过程类型。

测试如下:

UserDao:

package cn.qz.user;

import org.springframework.stereotype.Component;

@Component
public class UserDao {

    public void test1() {
    }
}

UserService:

package cn.qz.user;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

//@Component
//@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
//@Lazy
public class UserService implements InitializingBean, DisposableBean, BeanNameAware {

    // 构造
    public UserService() {
        System.out.println("=============UserService=====");
    }

    @Autowired
    public void setUserDao(UserDao userDao) {
        System.out.println("cn.qz.user.UserService.setUserDao====userDao");
    }

    // aware 接口
    @Override
    public void setBeanName(String name) {
        System.out.println("====setBeanName====" + name);
    }

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

    // InitializingBean
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("====afterPropertiesSet====");
    }

    // initMethod
    public void initMethod() {
        System.out.println("====initMethod====");
    }

    @PreDestroy
    public void PreDestroy() {
        System.out.println("PreDestroy  =============");
    }

    // DisposableBean
    @Override
    public void destroy() throws Exception {
        System.out.println("====destroy====");
    }

    // destroyMethod
    public void destroyMethod() {
        System.out.println("====destroyMethod====");
    }

}

配置类:

package cn.qz.user;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfiguration {

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public UserService userService() {
        return new UserService();
    }
}

编程式IoC如下:

package cn.qz;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
//@Import({ImpConfiguration.class})
//@EnableAspectJAutoProxy
public class App {
    public static void main(String[] args) {
        //在指定目录下生成动态代理类,我们可以反编译看一下里面到底是一些什么东西
//        System.setProperty("cglib.debugLocation", "F:/proxy");

        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(App.class);
        applicationContext.close();
    }
}

结果:

=============UserService=====
cn.qz.user.UserService.setUserDao====userDao
====setBeanName====userService
PostConstruct =============
====afterPropertiesSet====
====initMethod====
PreDestroy  =============
====destroy====
====destroyMethod====

总结:其生命周期图如下:

 (1) Aware 接口的实现顺序为:BeanNameAware-》BeanClassLoaderAware-》BeanFactoryAware

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

    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);
            }
        }
    }

(2) ApplicationContextAwareProcessor 是一个特殊的BeanPostProcessor, 里面主要是增加了ApplicationContext 的一些相关Aware

class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;


    /**
     * Create a new ApplicationContextAwareProcessor for the given context.
     */
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }


    @Override
    @Nullable
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }

}

(3) 在容器的BeanPostProcessor 中有几个全局的非常有用的类:(Spring 默认的一些BeanPostProcessor)

3.  BeanPostProcessor 的实现

 BeanPostProcessor是一个Bean的后置处理器,它可以监听容器触发的事件。将它向IoC容器注册后,容器中管理的Bean具备了接收IoC容器事件回调的能力。接口提供两个方法,一个是postProcessBeforeInitialization 在Bean的初始化之前提供回调入口;还有一个是postProcessAfterInitialization 在Bean的初始化之后提供回调入口。这两个回调都和容器管理Bean的生命周期相关。回调方法的参数都是一样的,分别是Bean的实例化对象和Bean的名字。

如下:

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;


public interface BeanPostProcessor {

    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

两个方法的调用都是在doCreateBean方法的initializeBean 方法调用时调用

(1)  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

(2) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

从上面代码可以看到,这两个Bean后置处理器定义的接口方法,一前一后,围绕着Bean定义的init-method方法调用。

测试如下:

package qz;

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

/**
 * @author: 乔利强
 * @date: 2021/2/19 15:47
 * @description:
 */
@Component
public class MyPostProcessor implements BeanPostProcessor {

    // Bean的初始化之前提供回调入口
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("userService".equals(beanName)) {
            System.out.println("====postProcessBeforeInitialization====");
        }
        return bean;
    }

    // Bean的初始化之后提供回调入口
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("userService".equals(beanName)) {
            System.out.println("====postProcessAfterInitialization====");
        }
        return bean;
    }
}

结果:

=============UserService=====
====setBeanName====userService
====postProcessBeforeInitialization====
PostConstruct =============
====afterPropertiesSet====
====initMethod====
====postProcessAfterInitialization====
PreDestroy  =============
====destroy====
====destroyMethod====

补充: BeanPostProcessor  的两个方法的返回值可以是以下三种情况

bean-不对IoC生成的bean做处理,原封不动的返回

proxrTarget-代理对象。也就是生成Cglib代理或者是JDK代理对象。 这对于接口类型接收的对象是可以的。(AOP代理对象的生成也是在BeanPostProcessor  中返回代理对象来修改引用完成的)

null 返回一个空对象

4. Aware的使用

  容器管理的Bean一般不需要了解容器的状态和直接使用容器,但在某些情况下,是需要在Bean中直接对IoC容器操作的,这时候就需要设定对容器的感知。SpringIoC容器也提供了该功能,通过特定的Aware接口实现。 

 在设置Bean的属性之后,调用初始化回调方法之前,Spring会调用sware接口的setter方法。

org.springframework.context.support.ApplicationContextAwareProcessor 作为BeanPostProcessor 的实现,对一系列的aware 回调进行了调用

class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;


    /**
     * Create a new ApplicationContextAwareProcessor for the given context.
     */
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }


    @Override
    @Nullable
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }

}

ApplicationContextAwareProcessor 注入到Spring的时机是在org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 准备IoC环境时。org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 如下:

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Register early post-processor for detecting inner beans as ApplicationListeners.
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

 测试:

package qz;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.*;
import org.springframework.core.io.ResourceLoader;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

//@Component
//@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
//@Lazy
public class UserService implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, ApplicationContextAware, MessageSourceAware, ApplicationEventPublisherAware, ResourceLoaderAware {

    // 构造
    public UserService() {
        System.out.println("=============UserService=====");
    }

    // BeanNameAware====可以在Bean中得到它在IoC容器中的Bean实例名称
    @Override
    public void setBeanName(String name) {
        System.out.println("====setBeanName====" + name);
    }

    // BeanFactoryAware====可以得到Bean所在的IoC容器,从而直接在Bean中石油IoC容器的服务
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("====beanFactory====" + beanFactory.getClass());
    }

    // ApplicationContextAware====可以在Bean得到Bean所在的应用上下文
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("====ApplicationContextAware====" + applicationContext.getClass());
    }

    // MessageSourceAware ==== 在Bean中得到消息源
    @Override
    public void setMessageSource(MessageSource messageSource) {
        System.out.println("====setMessageSource====" + messageSource.getClass());
    }

    // ApplicationEventPublisherAware ==== 在Bean中得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文的事件
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("====setApplicationEventPublisher====" + applicationEventPublisher.getClass());
    }

    // ResourceLoaderAware ==== 在Bean中得到ResourceLoader,从而在Bean中使用ResourceLoader 加载外部对应的Resource资源
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("====setResourceLoader====" + resourceLoader.getClass());
    }

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

    // InitializingBean
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("====afterPropertiesSet====");
    }

    // initMethod
    public void initMethod() {
        System.out.println("====initMethod====");
    }

    @PreDestroy
    public void PreDestroy() {
        System.out.println("PreDestroy  =============");
    }

    // DisposableBean
    @Override
    public void destroy() throws Exception {
        System.out.println("====destroy====");
    }

    // destroyMethod
    public void destroyMethod() {
        System.out.println("====destroyMethod====");
    }
}

结果:

=============UserService=====
====setBeanName====userService
====beanFactory====class org.springframework.beans.factory.support.DefaultListableBeanFactory
====setResourceLoader====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====setApplicationEventPublisher====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====setMessageSource====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====ApplicationContextAware====class org.springframework.context.annotation.AnnotationConfigApplicationContext
====postProcessBeforeInitialization====
PostConstruct =============
====afterPropertiesSet====
====initMethod====
====postProcessAfterInitialization====
PreDestroy  =============
====destroy====
====destroyMethod====

补充:FactoryBean 满足Bean 的生命周期,创建、属性注入、初始化(调用Aware接口、BeanPostProcessor.postProcessBeforeInitialization、InitializingBean.afterPropertiesSet、invokeCustomInitMethod、BeanPostProcessor.postProcessAfterInitialization)、使用、销毁。但是FactoryBean 的getObject 方法生成的对象不会走生命流程。

并且在IoC 过程中初始化单例对象时不会创建对象工厂getObject 创建的对象,对象工厂生成的对象只会在第一次使用getBean 获取时才会创建。

我们知道对于factoryBean, &beanName 获取factory 对象自身,beanName 获取其生成的getObject 对象

测试:

Test 类:

package cn.qz.factorybean;

import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;

public class Test implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware {

    public Test() {
        System.out.println("Test=====0");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("Test=====1");
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("Test=====2");
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        System.out.println("Test=====3");
    }
}

TestFactoryBean:

package cn.qz.factorybean;

import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;

public class TestFactoryBean implements FactoryBean<Test>, ResourceLoaderAware, BeanClassLoaderAware, InitializingBean {

    public TestFactoryBean() {
        System.out.println("TestFactoryBean created===1");
    }

    @Override
    public Test getObject() throws Exception {
        return new Test();
    }

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

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("TestFactoryBean created===2");
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("TestFactoryBean created===3");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("TestFactoryBean created===4");
    }
}

主类:

package cn.qz;

import cn.qz.factorybean.Test;
import cn.qz.factorybean.TestFactoryBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;

@Import({TestFactoryBean.class})
public class App {

    public App() {
        System.out.println("App created ======");
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(App.class);
        Test bean = applicationContext.getBean(Test.class);
        System.out.println(bean);
        applicationContext.close();
    }

}

结果

App created ======
TestFactoryBean created===1
TestFactoryBean created===2
TestFactoryBean created===3
TestFactoryBean created===4
Test=====0
cn.qz.factorybean.Test@1b1473ab

applicationContext.getBean(Test.class);代码跟踪:

1》org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class<T>)

2》org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>)

3》org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>, java.lang.Object...)

4》org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean

5》org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)

org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanNamesForType(org.springframework.core.ResolvableType)  获取合适的beanname

上面方法调用org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class<?>, boolean, boolean) 获取适用的beanName

上面方法调用org.springframework.beans.factory.support.DefaultListableBeanFactory#doGetBeanNamesForType    这里遍历factorybean,调用 Class<?> getObjectType(); 根据这个类型进行类型的判断

获取的适用的beanName为:

6》 获取到对应的beanName之后调用(beanName 是工厂的名称,requiredType类型是工厂生成的对象类型)。org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class<T>, java.lang.Object...)

7》org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

首先获取到对象工厂对象调用org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance

调用org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean 从对象工厂获取对象

org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean 直接调用对象的getObject 方法

【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】
原文地址:https://www.cnblogs.com/qlqwjy/p/14415269.html