Article From:https://www.cnblogs.com/ll409546297/p/9968050.html

  First, Aware interface, which is also one of Spring’s extensions, why should it be mentioned separately, because compared with BeanFactoryPostProcessor, BeanPostProcessor is more practical, and in specific industries.It can also be used flexibly in business, mainly to achieve the purpose of decoupling.

  Second, the commonly used Aware interfaces are: the first kind: BeanNameAware/BeanClassLoader Aware/BeanFactoryAware. Category 2: Embedded Value Resolver AwarE/Resource Loader Aware/Application Event Publisher Aware/MessageSource Aware/Application Context Aware. These two categories come toWhat kind of difference does it have? In fact, it doesn’t make much difference. But there are still big differences in source code implementation (unified later).

  3. Source code implementation:

  1、Category 1: BeanNameAware/BeanClassLoader Aware/BeanFactoryAware

  1)Realization:

import org.springframework.beans.factory.BeanNameAware;

/**
 * BeanNameAware/BeanClassLoaderAware/BeanFactoryAwareSimilar*/
public class TestBeanAware implements BeanNameAware{

    private String beanName;
    @Override
    public void setBeanName(String beanName) {
        System.out.println(beanName);
        this.beanName = beanName;
    }

    public String getBeanName() {
        return beanName;
    }
}

  2)What’s the difference?

  Here’s a brief explanation: BeanName / classLoader / beanFactory is available here as opposed to regular beans. It’s an enhancement of ordinary beans, and then a reasonable application is the key.

  3)Source code implementation part:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, this.getAccessControlContext());
        } else {
            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 BeanNameAware) {
            ((BeanNameAware)bean).setBeanName(beanName);
        }

        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware)bean).setBeanClassLoader(this.getBeanClassLoader());
        }

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

    }

  4)When to Call: Spring Source-Bean Load-2 3) Point D.3 do CreateBeaninitializeBean()Parts start, so this is actually called when getBean.

  5)Testing found: in enhanced containersrefreshMethod mediumfinishBeanFactoryInitializationhThis part of the call will be completed

  

  2、Category 2: Embedded Value Resolver Aware/Resource Loader Aware/Application Event Publisher Aware/MessageSource Aware/Application Context Aware

  1)Implementation: Here are two examples of Embedded Value Resolver Aware, Application Event Publisher Aware.

  a.EmbeddedValueResolverAware

import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.util.StringValueResolver;

import javax.annotation.PostConstruct;

public class TestEmbeddedValueResolverAware implements EmbeddedValueResolverAware {

    private StringValueResolver stringValueResolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
        this.stringValueResolver = stringValueResolver;
    }

    public String getProperties (String name) {
        String elName = "${"+ name +"}";
        return stringValueResolver.resolveStringValue(elName);
    }

    @PostConstruct
    public void test() {
        System.out.println(getProperties("name"));
    }
}

  Note: Here is the read mode configuration

  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>aware.properties</value>
            </list>
        </property>
    </bean>

  aware.properties

name=test
age=25
sex=boy

  Question: What does it have to do with this?StringValueResolverYou know, here it is.StringValueResolverPointing toPropertyPlaceholderConfigurerInner classPlaceholderResolvingStringValueResolver,Of course, there are different ways to implement it.

  private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
        private final PropertyPlaceholderHelper helper;
        private final PlaceholderResolver resolver;

        public PlaceholderResolvingStringValueResolver(Properties props) {
            this.helper = new PropertyPlaceholderHelper(PropertyPlaceholderConfigurer.this.placeholderPrefix, PropertyPlaceholderConfigurer.this.placeholderSuffix, PropertyPlaceholderConfigurer.this.valueSeparator, PropertyPlaceholderConfigurer.this.ignoreUnresolvablePlaceholders);
            this.resolver = PropertyPlaceholderConfigurer.this.new PropertyPlaceholderConfigurerResolver(props, (PropertyPlaceholderConfigurer.PropertyPlaceholderConfigurerResolver)null);
        }

        public String resolveStringValue(String strVal) throws BeansException {
            String value = this.helper.replacePlaceholders(strVal, this.resolver);
            return value.equals(PropertyPlaceholderConfigurer.this.nullValue) ? null : value;
        }
    }

  b.ApplicationEventPublisherAware

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

import javax.annotation.PostConstruct;

public class TestApplicationEventPublisherAware implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    public ApplicationEventPublisher getPublisher() {
        return publisher;
    }

    public class TestEvent extends ApplicationEvent {

        private Object object;

        public TestEvent(Object source, Object object) {
            super(source);
            this.object = object;
        }

        public Object getObject() {
            return object;
        }
    }

    @PostConstruct
    public void test() {
        publisher.publishEvent(new TestEvent(this, "test"));
    }
import org.springframework.context.ApplicationListener;

public class TestListener implements ApplicationListener<TestApplicationEventPublisherAware.TestEvent>{

    @Override
    public void onApplicationEvent(TestApplicationEventPublisherAware.TestEvent testEvent) {
        System.out.println("TestEvent is Happen" + testEvent.getObject());
    }
}

  Publish, monitor process believe. It’s very common in practical business. I’ll talk about the monitoring process later, but I won’t go into details here.

  Note: The publishing and monitoring process is more decoupled by using aware interface than by calling directly.

  2)Here’s the point. Where is this thing called? In fact, we have neglected a key point before.

  a.Look at the invocation first

  

  noticepostProcessBeforeInitializationYou should be happy, because that’s not what it’s all about.BeanPostProcessorIs the front-end call procedure of the interface?

  Questions can be referred to: Spring source – BeanPostProcessor – 3.3

  b.Question: We didn’t do it manually.BeanPostProcessorThe interface and the aware interface to do processing ah.

  By debug and viewing stack information, you can know that method calls are inApplicationContextAwareProcessorClass inside

package org.springframework.context.support;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.util.StringValueResolver;

class ApplicationContextAwareProcessor implements BeanPostProcessor {
    private final ConfigurableApplicationContext applicationContext;

    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
        if (System.getSecurityManager() != null && (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(new PrivilegedAction<Object>() {
                public Object run() {
                    ApplicationContextAwareProcessor.this.invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        } else {
            this.invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(new ApplicationContextAwareProcessor.EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
        }

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

    }

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

    private static class EmbeddedValueResolver implements StringValueResolver {
        private final ConfigurableBeanFactory beanFactory;

        public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
            this.beanFactory = beanFactory;
        }

        public String resolveStringValue(String strVal) {
            return this.beanFactory.resolveEmbeddedValue(strVal);
        }
    }
}

  c、There is another problem.ApplicationContextAwareProcessorWhere did you register?

   Viewed by source code inrefresh()Ofthis.prepareBeanFactory(beanFactory);Prepared in advanceApplicationContextAwareProcessor

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setBeanClassLoader(this.getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
        if (beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        Object systemEnvironment;
        if (!beanFactory.containsBean("systemProperties")) {
            try {
                systemEnvironment = System.getProperties();
            } catch (AccessControlException var4) {
                systemEnvironment = new ReadOnlySystemAttributesMap() {
                    protected String getSystemAttribute(String propertyName) {
                        try {
                            return System.getProperty(propertyName);
                        } catch (AccessControlException var3) {
                            if (AbstractApplicationContext.this.logger.isInfoEnabled()) {
                                AbstractApplicationContext.this.logger.info("Not allowed to obtain system property [" + propertyName + "]: " + var3.getMessage());
                            }

                            return null;
                        }
                    }
                };
            }

            beanFactory.registerSingleton("systemProperties", systemEnvironment);
        }

  Fourth: Aware interface part is so much, there are no specific implementations and usages, but compared with BeanFactoryPostProcessor, BeanPostProcessor. Aware will be more commonly used in practical applications, this part isSpring’s expansion is also a necessary and important part.

  Of course, I may still have some slips here, but also ask the big man to point out it! uuuuuuuuuuuu

Link of this Article: Spring Source – Aware-3.4

Leave a Reply

Your email address will not be published. Required fields are marked *