Skip to content

Commit

Permalink
增加classpath前缀支持
Browse files Browse the repository at this point in the history
  • Loading branch information
seaswalker committed Sep 3, 2017
1 parent 1621617 commit dcfaf53
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 46 deletions.
2 changes: 1 addition & 1 deletion etc/test.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?configurator.xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<china>
<area ranking="3">960</area>
<phone>86</phone>
Expand Down
45 changes: 23 additions & 22 deletions src/main/java/configurator/bean/BeanContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import configurator.util.Util;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -154,15 +155,15 @@ public Object get(String beanName) {
public <T> T get(Class<T> beanClass) {
assertNotClosed();
Objects.requireNonNull(beanClass);
List<BeanWrapper> candidates = new ArrayList<>();
List<BeanWrapper<T>> candidates = new ArrayList<>();
T result = null;
synchronized (monitor) {
for (Map.Entry<Class, BeanWrapper> entry : classMap.entrySet()) {
if (beanClass.isAssignableFrom(entry.getKey())) {
candidates.add(entry.getValue());
}
}
BeanWrapper beanWrapper = findEligibleCandidate(candidates, beanClass);
BeanWrapper<T> beanWrapper = findEligibleCandidate(candidates, beanClass);
if (beanWrapper != null) {
result = (T) loadBean(beanWrapper);
}
Expand All @@ -180,13 +181,13 @@ public <T> T get(Class<T> beanClass) {
*
* @throws IllegalStateException 如果发现多个候选者
*/
private <T> BeanWrapper findEligibleCandidate(List<BeanWrapper> candidates, Class<T> requiredType) {
private <T> BeanWrapper findEligibleCandidate(List<BeanWrapper<T>> candidates, Class<T> requiredType) {
int size = candidates.size();
BeanWrapper result = null;
BeanWrapper<T> result = null;
if (size == 1) {
result = candidates.get(0);
} else if (size > 1) {
for (BeanWrapper candidate : candidates) {
for (BeanWrapper<T> candidate : candidates) {
if (candidate.getTargetClass() == requiredType) {
result = candidate;
break;
Expand Down Expand Up @@ -234,8 +235,8 @@ public <T> List<T> getBeansWithType(Class<T> clazz) {
* <li>bean的{@link Scope}不为{@linkplain Scope#SINGLETON}.</li>
* </ul>
*/
private Object loadBean(BeanWrapper beanWrapper) {
Object result = beanWrapper.getTarget();
private <T> T loadBean(BeanWrapper<T> beanWrapper) {
T result = beanWrapper.getTarget();
if (beanWrapper.isCurrentlyInCreation()) {
if (!allowCircularReference || (result == null) || beanWrapper.getScope() != Scope.SINGLETON) {
throw new CircularReferenceException("Circular reference bean '" + beanWrapper.getBeanName() + "'.");
Expand All @@ -256,7 +257,7 @@ private Object loadBean(BeanWrapper beanWrapper) {
/**
* 将{@link BeanWrapper}的targetClass属性拼为字符串.
*/
private String getCandidatesInfo(List<BeanWrapper> candidates) {
private <T> String getCandidatesInfo(List<BeanWrapper<T>> candidates) {
List<String> classes = candidates.stream().map(beanWrapper -> beanWrapper.getTargetClass().getName()).
collect(Collectors.toList());
return ("[" + String.join(",", classes) + "}");
Expand All @@ -274,9 +275,9 @@ private void assertNotClosed() {
/**
* 创建bean实例.
*/
private Object createBean(BeanWrapper beanWrapper) {
Class beanClass = beanWrapper.getTargetClass();
Object instance = newInstance(beanClass);
private <T> T createBean(BeanWrapper<T> beanWrapper) {
Class<T> beanClass = beanWrapper.getTargetClass();
T instance = newInstance(beanClass);
if (instance != null) {
if (allowCircularReference && beanWrapper.getScope() == Scope.SINGLETON) {
//earlyReference
Expand All @@ -301,10 +302,10 @@ private Object createBean(BeanWrapper beanWrapper) {
*
* @param destroyHint 如果为false,那么容器将不会尝试调用销毁方法
*/
public void detachBean(Class<?> beanClass, boolean destroyHint) {
public <T> void detachBean(Class<T> beanClass, boolean destroyHint) {
assertNotClosed();
Objects.requireNonNull(beanClass);
BeanWrapper beanWrapper;
BeanWrapper<T> beanWrapper;
synchronized (monitor) {
beanWrapper = classMap.remove(beanClass);
nameMap.remove(beanWrapper.getBeanName());
Expand Down Expand Up @@ -409,7 +410,7 @@ private Object resolveArg(Parameter parameter) {
if (value != null) {
result = resolveConfByValue(parameter, name, parameter.getType(), parameter.getParameterizedType());
} else {
Class type = parameter.getType();
Class<?> type = parameter.getType();
if (type.isPrimitive()) {
throw new IllegalStateException("Can't inject to primitive type: " + parameter + ".");
}
Expand All @@ -436,8 +437,8 @@ private String getBeanName(Class beanClass) {
/**
* 构造{@link BeanWrapper}.
*/
private BeanWrapper newBeanWrapper(String beanName, Scope scope, Class beanClass) {
BeanWrapper wrapper = new BeanWrapper();
private <T> BeanWrapper<T> newBeanWrapper(String beanName, Scope scope, Class<T> beanClass) {
BeanWrapper<T> wrapper = new BeanWrapper<>();
wrapper.setBeanName(beanName);
wrapper.setScope(scope);
wrapper.setTargetClass(beanClass);
Expand All @@ -450,10 +451,10 @@ private BeanWrapper newBeanWrapper(String beanName, Scope scope, Class beanClass
* @param beanClass {@link Class} bean类型
* @throws IllegalStateException 如果构造失败
*/
private Object newInstance(Class beanClass) {
Object instance;
private <T> T newInstance(Class<T> beanClass) {
T instance;
try {
Constructor[] constructors = beanClass.getConstructors();
Constructor<?>[] constructors = beanClass.getConstructors();
int length = constructors.length;
if (length == 0) {
throw new IllegalStateException("There are no public constructors in " + beanClass.getName() + ".");
Expand All @@ -464,7 +465,7 @@ private Object newInstance(Class beanClass) {
Constructor constructor = constructors[0];
Parameter[] parameters = constructor.getParameters();
Object[] args = resolveArgs(parameters);
instance = constructor.newInstance(args);
instance = (T) constructor.newInstance(args);
} catch (InstantiationException e) {
throw new IllegalStateException("Construct bean failed, maybe there is no default constructor.", e);
} catch (IllegalAccessException e) {
Expand All @@ -486,7 +487,7 @@ private void injectConfs(Object instance, Class beanClass) {
/**
* 对标注在{@link Field}上的{@link Value}进行注入.
*/
private void injectConfByField(Object instance, Class beanClass) {
private void injectConfByField(Object instance, Class<?> beanClass) {
Set<Field> fields = ReflectionUtils.getAllFields(beanClass, ReflectionUtils.withAnnotation(Value.class));
for (Field field : fields) {
Object result = resolveConfByValue(field, field.getName(), field.getType(), field.getGenericType());
Expand Down Expand Up @@ -624,7 +625,7 @@ private String handlePrefix(String key) {
*
* @return true,如果满足
*/
private boolean isEligibleMap(Class clazz, Type type) {
private boolean isEligibleMap(Class<?> clazz, Type type) {
if (Map.class.isAssignableFrom(clazz)) {
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Expand Down
26 changes: 13 additions & 13 deletions src/main/java/configurator/bean/BeanWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,54 @@
*
* @author skywalker
*/
public class BeanWrapper {
public class BeanWrapper<T> {

private Scope scope;
private String beanName;
private Class targetClass;
private Object target;
private Class<T> targetClass;
private T target;
/**
* 是否正在创建对应的bean实例.
*/
private boolean currentlyInCreation = false;

public Scope getScope() {
Scope getScope() {
return scope;
}

public void setScope(Scope scope) {
void setScope(Scope scope) {
this.scope = scope;
}

public String getBeanName() {
String getBeanName() {
return beanName;
}

public void setBeanName(String beanName) {
void setBeanName(String beanName) {
this.beanName = beanName;
}

public Class getTargetClass() {
Class<T> getTargetClass() {
return targetClass;
}

public void setTargetClass(Class targetClass) {
void setTargetClass(Class<T> targetClass) {
this.targetClass = targetClass;
}

public Object getTarget() {
T getTarget() {
return target;
}

public void setTarget(Object target) {
void setTarget(T target) {
this.target = target;
}

public boolean isCurrentlyInCreation() {
boolean isCurrentlyInCreation() {
return currentlyInCreation;
}

public void setCurrentlyInCreation(boolean currentlyInCreation) {
void setCurrentlyInCreation(boolean currentlyInCreation) {
this.currentlyInCreation = currentlyInCreation;
}

Expand Down
19 changes: 17 additions & 2 deletions src/main/java/configurator/conf/AbstractPathBasedSource.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
package configurator.conf;

import configurator.util.Util;

/**
* 基于单一配置文件路径的{@link Source}.
*
* @author skywalker
*/
public abstract class AbstractPathBasedSource extends AbstractSource {
abstract class AbstractPathBasedSource extends AbstractSource {

protected final String path;

/**
* classpath路径支持.
*/
private static final String classPathPrefix = "classpath:";

protected AbstractPathBasedSource(String path) {
this.path = path;
if (Util.isEmpty(path)) {
throw new IllegalArgumentException("Param 'path' can not be null or empty.");
}
if (path.startsWith(classPathPrefix)) {
path = path.substring(classPathPrefix.length());
this.path = getClass().getClassLoader().getResource(path).getPath();
} else {
this.path = path;
}
}

}
13 changes: 7 additions & 6 deletions src/main/java/configurator/conf/JsonSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
import com.alibaba.fastjson.JSONObject;
import configurator.conf.exception.LoadException;

import java.io.IOException;
import java.io.*;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -46,8 +43,12 @@ public void load() throws LoadException {
* 将json配置文件读取为字符串.
*/
private String readAsString() throws IOException {
Path path = Paths.get(super.path);
List<String> lines = Files.readAllLines(path);
List<String> lines = new ArrayList<>();
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(super.path)));
String line;
while ((line = br.readLine()) != null) {
lines.add(line);
}
return String.join("", lines);
}

Expand Down
3 changes: 3 additions & 0 deletions src/resources/conf_classpath.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"classpath_name":"skywalker"
}
4 changes: 4 additions & 0 deletions src/resources/test_classpath.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<classpath>
<xml_value>10</xml_value>
</classpath>
4 changes: 4 additions & 0 deletions src/test/java/configurator/json/JsonHolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class JsonHolder {
private String[] locIds;
@Value(key = "interval.*")
private Map<String, String> interval;
@Value(key = "classpath_name")
private String classPathName;

@Value
public void setIp(String ip) {
Expand All @@ -52,6 +54,8 @@ public String toString() {
", msisdns=" + Arrays.toString(msisdns) +
", locIds=" + Arrays.toString(locIds) +
", interval=" + interval +
", classPathName='" + classPathName + '\'' +
'}';
}

}
6 changes: 5 additions & 1 deletion src/test/java/configurator/json/JsonTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package configurator.json;

import configurator.bean.BeanContainer;
import configurator.conf.CompositeSource;
import configurator.conf.JsonSource;
import configurator.conf.Source;
import configurator.conf.exception.LoadException;
Expand All @@ -17,8 +18,11 @@ public class JsonTest {
@Test
public void test() throws LoadException {
Source source = new JsonSource("etc/conf.json");
Source classPathSource = new JsonSource("classpath:conf_classpath.json");
CompositeSource compositeSource = new CompositeSource();
compositeSource.registerSource(source, classPathSource);
Injector injector = new Injector();
BeanContainer beanContainer = injector.basePackage("configurator.json").source(source).inject();
BeanContainer beanContainer = injector.basePackage("configurator.json").source(compositeSource).inject();
JsonHolder holder = beanContainer.get(JsonHolder.class);
System.out.println(holder);
}
Expand Down
3 changes: 3 additions & 0 deletions src/test/java/configurator/xml/Reporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public class Reporter {
@Value(key = "china.leaders#count")
private int leaderCount;
private HashMap<Object, String> all;
@Value(key = "classpath.xml_value")
private int classpathXMLValue;

public int getArea() {
return area;
Expand Down Expand Up @@ -68,6 +70,7 @@ public String toString() {
", leaders=" + Arrays.toString(leaders) +
", leaderCount=" + leaderCount +
", all=" + all +
", classpathXMLValue=" + classpathXMLValue +
'}';
}
}
6 changes: 5 additions & 1 deletion src/test/java/configurator/xml/XMLConfTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package configurator.xml;

import configurator.bean.BeanContainer;
import configurator.conf.CompositeSource;
import configurator.conf.Source;
import configurator.conf.XmlSource;
import configurator.conf.exception.LoadException;
Expand All @@ -17,8 +18,11 @@ public class XMLConfTest {
@Test
public void xml() throws LoadException {
Source confSource = new XmlSource("etc/test.xml");
Source classpathSource = new XmlSource("classpath:test_classpath.xml");
CompositeSource compositeSource = new CompositeSource();
compositeSource.registerSource(confSource, classpathSource);
Injector injector = new Injector();
BeanContainer beanContainer = injector.basePackage("configurator.xml").source(confSource).inject();
BeanContainer beanContainer = injector.basePackage("configurator.xml").source(compositeSource).inject();
Reporter reporter = beanContainer.get(SubReporter.class);
System.out.println(reporter);
}
Expand Down

0 comments on commit dcfaf53

Please sign in to comment.