Spring Bean初始化之后设置属性值

懒懒的小胖子 懒懒的小胖子
2018-11-21 14:34
53
0
package com.qzg.pay.common;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;

/**
 * @author Vincent
 * @date 2018/11/20
 * @desc
 */
@Component
public class Demo extends InstantiationAwareBeanPostProcessorAdapter
        implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware {
    /**
     * Callback that supplies the owning factory to a bean instance.
     * <p>Invoked after the population of normal bean properties
     * but before an initialization callback such as
     * {@link InitializingBean#afterPropertiesSet()} or a custom init-method.
     *
     * @param beanFactory owning BeanFactory (never {@code null}).
     *                    The bean can immediately call methods on the factory.
     * @throws BeansException in case of initialization errors
     * @see BeanInitializationException
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

    }

    /**
     * Set the name of the bean in the bean factory that created this bean.
     * <p>Invoked after population of normal bean properties but before an
     * init callback such as {@link InitializingBean#afterPropertiesSet()}
     * or a custom init-method.
     *
     * @param name the name of the bean in the factory.
     *             Note that this name is the actual bean name used in the factory, which may
     *             differ from the originally specified name: in particular for inner bean
     *             names, the actual bean name might have been made unique through appending
     *             "#..." suffixes. Use the {@link BeanFactoryUtils#originalBeanName(String)}
     *             method to extract the original bean name (without suffix), if desired.
     */
    @Override
    public void setBeanName(String name) {
       this.beanName=name;
    }

    private String beanName;

    @Override
    public boolean postProcessAfterInstantiation(final Object bean, final String beanName) throws BeansException {


        // 1、Annotation('@XxlConf'):resolves conf + watch
        if (!beanName.equals(this.beanName)) {

            ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
                @Override
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    if (field.isAnnotationPresent(Value.class)) {
                        System.out.println("fieldName=" + field.getName() + " beanName=" + beanName);
                    }
                }
            });
        }

        return super.postProcessAfterInstantiation(bean, beanName);
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        // 2、XML('$XxlConf{...}'):resolves placeholders + watch
        if (!beanName.equals(this.beanName)) {

            PropertyValue[] pvArray = pvs.getPropertyValues();
            for (PropertyValue pv : pvArray) {
                if (pv.getValue() instanceof TypedStringValue) {
                    String propertyName = pv.getName();
                    String typeStringVal = ((TypedStringValue) pv.getValue()).getValue();
                    if (xmlKeyValid(typeStringVal)) {

                        // object + property
                        String confKey = xmlKeyParse(typeStringVal);
                        System.out.println(confKey+" beanName="+beanName);

                    }
                }
            }

        }

        return super.postProcessPropertyValues(pvs, pds, bean, beanName);
    }
    private static final String placeholderPrefix = "${";
    private static final String placeholderSuffix = "}";

    /**
     * valid xml
     *
     * @param originKey
     * @return
     */
    private static boolean xmlKeyValid(String originKey){
        boolean start = originKey.startsWith(placeholderPrefix);
        boolean end = originKey.endsWith(placeholderSuffix);
        if (start && end) {
            return true;
        }
        return false;
    }

    /**
     * parse xml
     *
     * @param originKey
     * @return
     */
    private static String xmlKeyParse(String originKey){
        if (xmlKeyValid(originKey)) {
            // replace by xxl-conf
            String key = originKey.substring(placeholderPrefix.length(), originKey.length() - placeholderSuffix.length());
            return key;
        }
        return null;
    }
    /**
     * Invoked by a BeanFactory on destruction of a singleton.
     *
     * @throws Exception in case of shutdown errors.
     *                   Exceptions will get logged but not rethrown to allow
     *                   other beans to release their resources too.
     */
    @Override
    public void destroy() throws Exception {

    }

    /**
     * Invoked by a BeanFactory after it has set all bean properties supplied
     * (and satisfied BeanFactoryAware and ApplicationContextAware).
     * <p>This method allows the bean instance to perform initialization only
     * possible when all bean properties have been set and to throw an
     * exception in the event of misconfiguration.
     *
     * @throws Exception in the event of misconfiguration (such
     *                   as failure to set an essential property) or if initialization fails.
     */
    @Override
    public void afterPropertiesSet() throws Exception {

    }
}

参考XXL-conf实现,做记录,便于以后使用

发表评论