package org.test4j.module.spring.strategy.register;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.test4j.module.core.utility.MessageHelper;
import org.test4j.module.spring.annotations.AutoBeanInject;
import org.test4j.module.spring.annotations.AutoBeanInject.BeanMap;
import org.test4j.module.spring.exception.FindBeanImplClassException;
import org.test4j.module.spring.strategy.ImplementorFinder;
import org.test4j.tools.commons.ClazzHelper;
import org.test4j.tools.commons.StringHelper;
/**
* spring bean定义
*
* @author darui.wudr
*
*/
@SuppressWarnings("rawtypes")
public class RegisterBeanDefinition {
private final DefaultListableBeanFactory factory;
private final AutoBeanInject autoBeanInject;
private final List<BeanMap> mappingRules;
private boolean allowAutoInject;
public RegisterBeanDefinition(final DefaultListableBeanFactory factory, final AutoBeanInject autoBeanInject) {
this.factory = factory;
this.autoBeanInject = autoBeanInject;
if (autoBeanInject == null || autoBeanInject.value() == false) {
this.allowAutoInject = false;
this.mappingRules = new ArrayList<BeanMap>();
} else {
this.allowAutoInject = true;
this.mappingRules = checkBeanMap(this.autoBeanInject.maps());
}
}
private final static String VALID_PACK_REGEX = "[\\w_$\\.\\*]+";
/**
* 验证@BeanMap属性的有效性
*
* @param autoMaps
* @return
*/
private static List<BeanMap> checkBeanMap(BeanMap[] autoMaps) {
List<BeanMap> mapping = new ArrayList<BeanMap>();
if (autoMaps == null || autoMaps.length == 0) {
return mapping;
}
for (BeanMap autoMap : autoMaps) {
String intf = autoMap.intf();
String impl = autoMap.impl();
if (StringHelper.isBlankOrNull(intf) || StringHelper.isBlankOrNull(impl)) {
throw new RuntimeException(String.format("Illegal value @AutoMap(intf=\"%s\",impl=\"%s\") value", intf,
impl));
}
if (intf.matches(VALID_PACK_REGEX) == false || impl.matches(VALID_PACK_REGEX) == false) {
throw new RuntimeException(String.format("Illegal value @AutoMap(intf=\"%s\",impl=\"%s\") value", intf,
impl));
}
mapping.add(autoMap);
}
return mapping;
}
/**
* 改id的bean是否已经定义
*
* @param beanName
* @return
*/
public boolean doesHaveRegisted(String beanName) {
boolean doesRegisted = factory.containsBeanDefinition(beanName);
return doesRegisted;
}
public Class findImplementClass(Class ownerClazz, String propName, Class propClazz)
throws FindBeanImplClassException {
Class implClazz = ImplementorFinder.findImplClazz(ownerClazz, propName, propClazz, mappingRules);
return implClazz;
}
public void register(String beanName, AbstractBeanDefinition beanDefinition) {
factory.registerBeanDefinition(beanName, beanDefinition);
}
/**
* 如果忽略异常,则只打印消息;否则抛出运行时异常
*
* @param e
*/
public void ignoreNotFoundException(Throwable e) {
if (this.autoBeanInject == null || this.autoBeanInject.ignoreNotFound()) {
MessageHelper.warn("ignore NotFound:" + (e == null ? "<null>" : e.getMessage()));
} else {
throw new RuntimeException(e);
}
}
/**
* 判断是否允许自动注入接口bean(自动查找实现)
*
* @return
*/
public boolean allowAutoInject() {
return this.allowAutoInject;
}
/**
* 判断是否运行注册该属性<br>
*
* @param beanName
* @return
*/
public boolean allowAutoInject(String beanName) {
if (this.allowAutoInject == false) {
return false;
}
boolean registed = this.doesHaveRegisted(beanName);
return !registed;
}
/**
* 默认会被排除掉的属性名称
*/
private static Set<String> DEFAULT_EXCLUDE_PROPERTIES = new HashSet<String>() {
private static final long serialVersionUID = 705657590280935844L;
{
add("class");
add("override");
}
};
/**
* 默认会被排除掉自动注册的属性包类型
*/
private static Set<String> DEFAULT_EXCLUDE_PACKAGES = new HashSet<String>() {
private static final long serialVersionUID = -102059987060939894L;
{
add("org.springframework.");
add("java.");
add("javax.");
add("org.spring.");
}
};
/**
* 是否排除该属性的注册<br>
* o 枚举类型、Annotation,数组或者primitive类型<br>
* o 默认排除的属性,如 Object 定义的class,ovveride<br>
* o 显式排除的类型,如java.*, javax.*和org.spring.*等<br>
* o 已经在factory中定义过的属性<br>
*
* @param name
* @param clazz
* @return
*/
public boolean isExcludeProperty(String name, Class clazz) {
if (clazz.isEnum() || clazz.isAnnotation() || clazz.isArray() || clazz.isPrimitive()) {
return true;
}
boolean isExcludeProperty = isExcludeProperty(name);
if (isExcludeProperty) {
return true;
}
boolean isExcludeClazz = isExcludePackage(clazz.getName());
return isExcludeClazz;
}
/**
* 是否排除注入的指定的属性
*
* @param property
* 要注入bean的属性
* @param beanFactory
* spring容器
* @param excludeProperties
* 显式指定要排除的属性名称
* @return
*/
private boolean isExcludeProperty(String property) {
if (StringHelper.isBlankOrNull(property)) {
return true;
}
if (DEFAULT_EXCLUDE_PROPERTIES.contains(property) || factory.containsBeanDefinition(property)) {
return true;
}
String[] excludeProperties = this.autoBeanInject.excludeProperties();
if (excludeProperties == null || excludeProperties.length == 0) {
return false;
}
for (String excludeProperty : excludeProperties) {
if (property.equals(excludeProperty)) {
return true;
}
}
return false;
}
/**
* 以下属性不能自动注入<br>
* o spring本身提供的bean必须在文件中配置 <br>
* o java.* 和 javax.* package<br>
* o @AutoBeanInject 中显式排除的package
*
* @param clazzname
* 要注入的属性类型
* @param excludePackages
* 显式排除的类型
* @return
*/
private boolean isExcludePackage(String clazzname) {
for (String excludePackage : DEFAULT_EXCLUDE_PACKAGES) {
if (clazzname.startsWith(excludePackage)) {
return true;
}
}
final String[] excludePackages = this.autoBeanInject.excludePackages();
if (excludePackages == null || excludePackages.length == 0) {
return false;
}
for (String excludePackage : excludePackages) {
String regex = ClazzHelper.getPackageRegex(excludePackage);
if (clazzname.matches(regex)) {
return true;
}
}
return false;
}
}