我想在类中使用带有@Inject批注的同一对象。
因此在此测试中:我需要向Test和C类中注入相同的'b'对象。
我的DefaultBeanFactory
有什么问题?
这是我的测试主要课程(注入A,B和C):
public class Test {
@Inject
private A a;
@Inject
private B b;
@Inject
private C c;
public static void main(String [] arg) {
BeanFactory f = new DefaultBeanFactory();
f.registerBean(Test.class.getName());
Test test = (Test)f.getBean("Test");
test.start();
}
private void start() {
c.tryTosetB();
System.out.println("b in: '"+this.getClass().getName()+"' with id["+b.getId()+"] with hashcode: ["+b.hashCode()+"]");
c.printB();
}
}
注入的类:
A(注入A):
public class A {
@Inject
private B b;
public A(){
System.out.println("A constructor");
}
}
B:
public class B {
private String id;
public B(){
System.out.println("B constructor");
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
C(注入B):
public class C {
@Inject
private B b;
public C(){
System.out.println("A constructor");
}
public void tryTosetB(){
b.setId("C setted id");
}
public void printB(){
System.out.println("b in: '"+this.getClass().getName()+"' with id["+b.getId()+"] with hashcode: ["+b.hashCode()+"]");
}
}
这是我的BeanFactory:
public class DefaultBeanFactory implements BeanFactory {
private static final Map<String, BeanDefinition> BEAN_DEF_MAP = new HashMap<>();
public static Map<String, BeanDefinition> getBeanDefMap() {
return BEAN_DEF_MAP;
}
public static Map<String, Object> getSingletonMap() {
return SINGLETON_MAP;
}
private static final Map<String, Object> SINGLETON_MAP = new HashMap<String, Object>();
private static String generateBeanId(String className) {
return className.substring(className.lastIndexOf('.') + 1, className.length());
}
@Override
public void registerBean(String classname) {
registerBean(classname, Scope.SINGLETON);
}
@Override
public void registerBean(String classname, Scope scope) {
System.out.println("Register been: "+classname +" "+scope.name());
String beanId = generateBeanId(classname);
if (BEAN_DEF_MAP.containsKey(beanId)) {
System.out.println("Bean already registered to the container {" + beanId + "}");
return;
}
BeanDefinition def = new BeanDefinition();
def.setClassFqdn(classname);
def.setId(beanId);
def.setScope(scope);
BEAN_DEF_MAP.put(beanId, def);
}
@Override
public Object getBean(String id) {
System.out.println("Request to get Bean with id: "+id);
BeanDefinition def = BEAN_DEF_MAP.get(id);
if (def == null) {
throw new IllegalArgumentException("Missing bean from the container with id: " + id);
}else{
System.out.println("\tBean found in BEAN_DEF_MAP with id: "+id);
}
Object instance = null;
if (Scope.SINGLETON == def.getScope()) {
if (SINGLETON_MAP.containsKey(id)) {
System.out.println("\tSINGLETON_MAP contained: "+id);
instance = SINGLETON_MAP.get(id);
} else {
System.out.println("\tSINGLETON_MAP not contained so create object: "+def+ " with id: "+id);
instance = createObject(def);
SINGLETON_MAP.put(id, instance);
}
} else if (Scope.PROTOTYPE == def.getScope()) {
instance = createObject(def);
}
return instance;
}
private static void injectDependencies(Object containerObject, Field f) {
System.out.println("Request to inject field with name: "+f.getName());
if ((f.getAnnotation(Inject.class) != null) && !f.getClass().isPrimitive()) {
System.out.println("\t@Inject: "+f.getType().getName());
Object fieldValue = null;
try {
fieldValue = f.getType().newInstance();
f.setAccessible(true);
f.set(containerObject, fieldValue);
for (Field transitiveDependency : f.getType().getDeclaredFields()) {
injectDependencies(fieldValue, transitiveDependency);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static List<Field> getAllField(List<Field> fields, Class<?> clazz) {
List<Field> allField = new ArrayList<Field>();
allField.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (clazz.getSuperclass() != null) {
allField.addAll(getAllField(allField, clazz.getSuperclass()));
}
return allField;
}
private static Object createObject(BeanDefinition def) {
System.out.println("Request to get create Object with def class: "+def.getClassFqdn());
Object instance = null;
Class<?> beanClazz = null;
try {
beanClazz = Class.forName(def.getClassFqdn());
instance = beanClazz.newInstance();
List<Field> fields = getAllField(new ArrayList<Field>(), beanClazz);
for (Field f : fields) {
System.out.println("\tinject dependencie field with name: "+f.getName());
injectDependencies(instance, f);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return instance;
}