1. 程式人生 > 其它 >Spring Aware介面

Spring Aware介面

Aware

adj. 知道的,明白的,察覺到的,意識到的

package com.example.zylspringboot.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class ZYLAwareTest implements ApplicationContextAware, BeanNameAware, EnvironmentAware, InitializingBean {

    private static ApplicationContext context;
    private static String name;
    private static Environment env;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    @Override
    public void setBeanName(String s) {
        name = s;
    }

    @Override
    public void setEnvironment(Environment environment) {
        env = environment;
    }

    public void show(){
        log.info("ZYLAwareTest-->context:{},name:{},env:{}",context,name,env);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.show();
    }
}

console:

2022-11-30 10:41:21.767 INFO 12408 --- [ main] c.e.zylspringboot.util.ZYLAwareTest : ZYLAwareTest-->context:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@4535b6d5, started on Wed Nov 30 10:41:15 CST 2022,name:ZYLAwareTest,env:ApplicationServletEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, SimpleCommandLinePropertySource {name='commandLineArgs'}, StubPropertySource {name='servletConfigInitParams'}, ServletContextPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='Config resource 'class path resource [application.properties]' via location 'optional:classpath:/''}]}

tips:

可是@Autowired註解都可以實現上面的三種方法,為什麼還需要自己手動實現呢?

  • @Autowired的解析是需要用到bean的後處理器,屬於擴充套件功能
  • 而Aware介面屬於內建功能,不加任何擴充套件,Spring就能識別
  • 內建的注入和初始化不受擴充套件功能的影響,總會被執行

原始碼:

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

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

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

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.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 = this.getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
            }
        }

        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware)bean).setBeanFactory(this);
        }
    }
}