All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.javaclub.configcenter.spring.property.SpringValue Maven / Gradle / Ivy

The newest version!
package com.github.javaclub.configcenter.spring.property;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;

import com.github.javaclub.toolbox.ToolBox.Objects;

/**
 * Spring @org.springframework.beans.factory.annotation.Value method info
 */
public class SpringValue {
	
	private static final Logger logger = LoggerFactory.getLogger(SpringValue.class);

	private MethodParameter methodParameter;
	private Field field;
	private WeakReference beanRef;
	private String beanName;
	private String key;
	private String placeholder;
	private Class targetType;
	private Type genericType;
	private boolean isJson;

	public SpringValue(String key, String placeholder, Object bean, String beanName, Field field, boolean isJson) {
		this.beanRef = new WeakReference<>(bean);
		this.beanName = beanName;
		this.field = field;
		this.key = key;
		this.placeholder = placeholder;
		this.targetType = field.getType();
		this.isJson = isJson;
		if (isJson) {
			this.genericType = field.getGenericType();
		}
	}

	public SpringValue(String key, String placeholder, Object bean, String beanName, Method method, boolean isJson) {
		this.beanRef = new WeakReference<>(bean);
		this.beanName = beanName;
		this.methodParameter = new MethodParameter(method, 0);
		this.key = key;
		this.placeholder = placeholder;
		Class[] paramTps = method.getParameterTypes();
		this.targetType = paramTps[0];
		this.isJson = isJson;
		if (isJson) {
			this.genericType = method.getGenericParameterTypes()[0];
		}
	}

	public void update(Object newVal) throws IllegalAccessException, InvocationTargetException {
		if (isField()) {
			Object oldVal = getFieldOriginalValue();
//			logger.info("Value={}, key={}, beanName={}, field={}.{}", oldVal, key, beanName, 
//					beanRef.get().getClass().getName(), field.getName());
			if (!Objects.equals(newVal, oldVal)) {
				injectField(newVal);
			}
		} else {
			injectMethod(newVal);
		}
	}
	
	private Object getFieldOriginalValue() throws IllegalArgumentException, IllegalAccessException {
		boolean accessible = field.isAccessible();
		try {
			field.setAccessible(true);
			return field.get(beanRef.get());
		} finally {
			field.setAccessible(accessible);
		}
	}

	private void injectField(Object newVal) throws IllegalAccessException {
		Object bean = beanRef.get();
		if (bean == null) {
			return;
		}
		boolean accessible = field.isAccessible();
		field.setAccessible(true);
		field.set(bean, newVal);
		field.setAccessible(accessible);
		logger.info("AutoUpdate configValue successfully, newValue={}, {}", newVal, this);
	}

	private void injectMethod(Object newVal) throws InvocationTargetException, IllegalAccessException {
		Object bean = beanRef.get();
		if (bean == null) {
			return;
		}
		methodParameter.getMethod().invoke(bean, newVal);
		logger.info("AutoUpdate configValue successfully, newValue={}, {}", newVal, this);
	}

	public String getBeanName() {
		return beanName;
	}

	public Class getTargetType() {
		return targetType;
	}

	public String getPlaceholder() {
		return this.placeholder;
	}

	public MethodParameter getMethodParameter() {
		return methodParameter;
	}

	public boolean isField() {
		return this.field != null;
	}

	public Field getField() {
		return field;
	}

	public Type getGenericType() {
		return genericType;
	}

	public boolean isJson() {
		return isJson;
	}

	boolean isTargetBeanValid() {
		return beanRef.get() != null;
	}

	@Override
	public String toString() {
		Object bean = beanRef.get();
		if (bean == null) {
			return "";
		}
		if (isField()) {
			return String.format("key=%s, beanName=%s, field=%s.%s", key, beanName, bean.getClass().getName(),
					field.getName());
		}
		return String.format("key=%s, beanName=%s, method=%s.%s", key, beanName, bean.getClass().getName(),
				methodParameter.getMethod().getName());
	}
}