Skip to content

Commit

Permalink
resolve #238
Browse files Browse the repository at this point in the history
  • Loading branch information
hellokaton committed Nov 21, 2018
1 parent 33fb823 commit 503330d
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 31 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/blade/ioc/Injector.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ public interface Injector {
*/
void injection(Object bean);

void injection(Object bean, Object value);

}
2 changes: 1 addition & 1 deletion src/main/java/com/blade/ioc/SimpleIoc.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public <T> T addBean(Class<T> type) {
@Override
public Object createBean(Class<?> type) {
BeanDefine beanDefine = createBeanDefine(type, true);
IocKit.injection(this, Objects.requireNonNull(beanDefine));
IocKit.initInjection(this, Objects.requireNonNull(beanDefine));
IocKit.injectionValue(WebContext.blade().environment(), beanDefine);
return beanDefine.getBean();
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/blade/ioc/annotation/Inject.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import java.lang.annotation.Target;

/**
* Automatic injection
* Automatic initInjection
*
* @author <a href="mailto:biezhi.me@gmail.com" target="_blank">biezhi</a>
* @since 1.5
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/blade/ioc/bean/BeanDefine.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class BeanDefine {
private Object bean;
private Class<?> type;
private boolean isSingleton;
private boolean hasPrototypeField;
private boolean fieldHasPrototype;

public BeanDefine(Object bean) {
this(bean, bean.getClass());
Expand Down Expand Up @@ -53,11 +53,11 @@ public void setSingleton(boolean isSingleton) {
this.isSingleton = isSingleton;
}

public boolean isHasPrototypeField() {
return hasPrototypeField;
public boolean isFieldHasPrototype() {
return fieldHasPrototype;
}

public void setHasPrototypeField(boolean hasPrototypeField) {
this.hasPrototypeField = hasPrototypeField;
public void setFieldHasPrototype(boolean fieldHasPrototype) {
this.fieldHasPrototype = fieldHasPrototype;
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/blade/ioc/bean/FieldInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ public FieldInjector(Ioc ioc, Field field) {
this.field = field;
}

public Class<?> getType() {
return field.getType();
}

public boolean isSingleton() {
return IocKit.isSingleton(field.getType());
}
Expand All @@ -34,11 +38,24 @@ public void injection(Object bean) {
if (value == null) {
throw new IllegalStateException("Can't inject bean: " + fieldType.getName() + " for field: " + field);
}
injection(bean, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

@Override
public void injection(Object bean, Object value) {
try {
field.setAccessible(true);
field.set(bean, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public boolean hasInjectFields() {
return field.getType().getDeclaredFields().length > 0;
}

}
39 changes: 23 additions & 16 deletions src/main/java/com/blade/ioc/bean/ValueInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.lang.reflect.Field;
import java.util.*;

/**
* Config annotation can be injected
*
Expand All @@ -14,13 +15,13 @@
@Slf4j
public class ValueInjector implements Injector {
private Environment environment;
private Field target;
private String key;
private Field target;
private String key;

public ValueInjector(Environment environment, Field target, String key) {
this.environment = environment;
this.target = target;
this.key = key;
this.target = target;
this.key = key;
}

@Override
Expand All @@ -31,40 +32,46 @@ public void injection(Object bean) {
target.setAccessible(true);
Optional<String> value = environment.get(key);
if (!value.isPresent()) {
log.warn("config is absent,so can't be injected:target is {}",bean.getClass().getName());
log.warn("config is absent,so can't be injected:target is {}", bean.getClass().getName());
return;
}
if (value.get().isEmpty()) {
log.warn("config is empty,so can't be injected:target is {}",bean.getClass().getName());
log.warn("config is empty,so can't be injected:target is {}", bean.getClass().getName());
return;
}
//target field type is String
if (clazz.isAssignableFrom(String.class)) {
target.set(bean, value.isPresent()? value.get() : "");
target.set(bean, value.isPresent() ? value.get() : "");
return;
}

//List and Map support,just support String element
String split = environment.get("value.split",",");
String mapSplit = environment.get("value.map.split",":");
String split = environment.get("value.split", ",");
String mapSplit = environment.get("value.map.split", ":");
if (clazz.isAssignableFrom(List.class)) {
target.set(bean,Arrays.asList(value.get().split(split)));
target.set(bean, Arrays.asList(value.get().split(split)));
return;
}
Map<String,String> map = new HashMap(16);
Map<String, String> map = new HashMap(16);
if (clazz.isAssignableFrom(Map.class)) {
Arrays.stream(value.get().split(split))
.filter(d -> d.indexOf(mapSplit) != -1)
.map(d -> d.split(mapSplit))
.forEach(keyValue -> map.put(keyValue[0],keyValue[1]));
target.set(bean,map);
.forEach(keyValue -> map.put(keyValue[0], keyValue[1]));
target.set(bean, map);
return;
}
}else {
log.warn("key is empty,so can't be injected:target is {}",bean.getClass().getName());
} else {
log.warn("key is empty,so can't be injected:target is {}", bean.getClass().getName());
}
} catch (IllegalAccessException e) {
log.error("inject config error! key is {},bean is {}",key,bean.getClass().getSimpleName(),e);
log.error("inject config error! key is {},bean is {}", key, bean.getClass().getSimpleName(), e);
}
}

@Override
public void injection(Object bean, Object value) {
// TODO
}

}
28 changes: 23 additions & 5 deletions src/main/java/com/blade/kit/IocKit.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.blade.ioc.bean.ClassDefine;
import com.blade.ioc.bean.FieldInjector;
import com.blade.ioc.bean.ValueInjector;
import com.blade.mvc.WebContext;
import com.blade.mvc.annotation.Path;
import lombok.experimental.UtilityClass;

Expand All @@ -51,7 +52,7 @@ public class IocKit {
* @return return FieldInjector
*/
private static List<FieldInjector> getInjectFields(Ioc ioc, ClassDefine classDefine) {
List<FieldInjector> injectors = new ArrayList<>(8);
List<FieldInjector> injectors = new ArrayList<>();
for (Field field : classDefine.getDeclaredFields()) {
if (null != field.getAnnotation(InjectWith.class) || null != field.getAnnotation(Inject.class)) {
injectors.add(new FieldInjector(ioc, field));
Expand Down Expand Up @@ -92,16 +93,33 @@ public static void injection(Ioc ioc, BeanDefine beanDefine) {
ClassDefine classDefine = ClassDefine.create(beanDefine.getType());
List<FieldInjector> fieldInjectors = getInjectFields(ioc, classDefine);

Object bean = beanDefine.getBean();
fieldInjectors.forEach(fieldInjector -> {
Object fieldInstance = ReflectKit.newInstance(fieldInjector.getType());
if (fieldInjector.hasInjectFields()) {
injection(ioc, new BeanDefine(fieldInstance));
}
fieldInjector.injection(bean, fieldInstance);
});
}

public static void initInjection(Ioc ioc, BeanDefine beanDefine) {
ClassDefine classDefine = ClassDefine.create(beanDefine.getType());
List<FieldInjector> fieldInjectors = getInjectFields(ioc, classDefine);

Object bean = beanDefine.getBean();

AtomicBoolean hasPrototypeField = new AtomicBoolean(false);

fieldInjectors.stream().filter(FieldInjector::isSingleton).forEach(fieldInjector -> {
fieldInjector.injection(bean);
hasPrototypeField.set(true);
fieldInjectors.forEach(fieldInjector -> {
if (fieldInjector.isSingleton()) {
fieldInjector.injection(bean);
} else {
hasPrototypeField.set(true);
}
});

beanDefine.setHasPrototypeField(hasPrototypeField.get());
beanDefine.setFieldHasPrototype(hasPrototypeField.get());
}

public static void injectionValue(Environment environment, BeanDefine beanDefine) {
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/com/blade/mvc/RouteContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.blade.mvc;

import com.blade.ioc.bean.BeanDefine;
import com.blade.kit.IocKit;
import com.blade.mvc.http.Body;
import com.blade.mvc.http.Request;
Expand Down Expand Up @@ -527,8 +528,14 @@ public void initRoute(Route route) {
boolean singleton = IocKit.isSingleton(route.getTargetType());

if (singleton) {
Object target = WebContext.blade().ioc().getBean(route.getTargetType());
this.route.setTarget(target);
BeanDefine beanDefine = WebContext.blade().ioc().getBeanDefine(route.getTargetType());
if(beanDefine.isFieldHasPrototype()){
// reset initialize
IocKit.injection(WebContext.blade().ioc(), beanDefine);
} else {
Object target = WebContext.blade().ioc().getBean(route.getTargetType());
this.route.setTarget(target);
}
} else {
Object target = WebContext.blade().ioc().createBean(route.getTargetType());
this.route.setTarget(target);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/blade/server/netty/NettyServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ private void initIoc() {

if (BladeKit.isNotEmpty(beanDefines)) {
beanDefines.forEach(b -> {
IocKit.injection(ioc, b);
IocKit.initInjection(ioc, b);
IocKit.injectionValue(environment, b);
List<TaskStruct> cronExpressions = BladeKit.getTasks(b.getType());
if (null != cronExpressions) {
Expand Down

0 comments on commit 503330d

Please sign in to comment.