/** Adds object instance to the container as singleton bean. */ public void addBean(String name, Object bean, WiringMode wiringMode) { wiringMode = petiteConfig.resolveWiringMode(wiringMode); registerPetiteBean(bean.getClass(), name, SingletonScope.class, wiringMode, false); BeanDefinition def = lookupExistingBeanDefinition(name); Map<String, Object> acquiredBeans = new HashMap<String, Object>(); acquiredBeans.put(name, bean); wireBeanInjectParamsAndInvokeInitMethods(def, bean, acquiredBeans); def.scopeRegister(bean); }
@Test public void testPrototype() throws Exception { // 1.创建Bean工厂 DefaultBeanFactory bf = new DefaultBeanFactory(); // 2.创建原型 Bean定义 BeanDefinition bd = new BeanDefinition(); bd.setId("bean"); bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); bd.setClazz(HelloImpl2.class.getName()); bf.registerBeanDefinition(bd); // 对于原型Bean每次应该返回一个全新的Bean System.out.println(bf.getBean("bean") != bf.getBean("bean")); }
@Test public void testSingleton() throws Exception { // 1.创建Bean工厂 DefaultBeanFactory bf = new DefaultBeanFactory(); // 2.创建单例 Bean定义 BeanDefinition bd = new BeanDefinition(); bd.setId("bean"); bd.setScope(BeanDefinition.SCOPE_SINGLETON); bd.setClazz(HelloImpl2.class.getName()); bf.registerBeanDefinition(bd); // 对于单例Bean应该返回同一个Bean System.out.println(bf.getBean("bean") == bf.getBean("bean")); }
private void injectBeansToComponents() { for (Class<?> c : componentsClasses) { try { Object object = c.newInstance(); for (Field f : c.getDeclaredFields()) { if (f.isAnnotationPresent(Inject.class)) { f.setAccessible(true); Class<?> fieldClass = f.getType(); BeanDefinition beanDefinition = findBeenByClass(fieldClass); f.set(object, beanDefinition.getInstance()); } } preparedComponents.put(c.getName(), new SingletonBeanDefinition(c, object)); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } }
/** Invokes all init methods, if they exist. Also resolves destroy methods. */ protected void invokeInitMethods( Object bean, BeanDefinition def, InitMethodInvocationStrategy invocationStrategy) { if (def.initMethods == null) { def.initMethods = petiteResolvers.resolveInitMethodPoint(bean); } if (def.destroyMethods == null) { def.destroyMethods = petiteResolvers.resolveDestroyMethodPoint(bean); } for (InitMethodPoint initMethod : def.initMethods) { if (invocationStrategy != initMethod.invocationStrategy) { continue; } try { initMethod.method.invoke(bean); } catch (Exception ex) { throw new PetiteException("Invalid init method: " + initMethod, ex); } } }
/** * Returns Petite bean instance. * * @see PetiteContainer#createBean(Class) */ protected Object getBean(String name, Map<String, Object> acquiredBeans) { // First check if bean is already acquired within this call. // This prevents cyclic dependencies problem. It is expected than single // object tree path contains less elements, therefore, this search is faster // then the next one. Object bean = acquiredBeans.get(name); if (bean != null) { if (bean == Void.TYPE) { throw new PetiteException("Cycle dependencies on constructor injection detected!"); } return bean; } // Lookup for registered bean definition. BeanDefinition def = lookupBeanDefinition(name); if (def == null) { // try provider ProviderDefinition providerDefinition = providers.get(name); if (providerDefinition != null) { return invokeProvider(providerDefinition); } return null; } // Find the bean in its scope bean = def.scopeLookup(); if (bean == null) { // Create new bean in the scope bean = newBeanInstance(def, acquiredBeans); wireBeanInjectParamsAndInvokeInitMethods(def, bean, acquiredBeans); def.scopeRegister(bean); } return bean; }
@Override public Object getComponent(Class<?> clazz) { Object objectToReturn = preparedComponents.get(clazz.getName()).getInstance(); if (objectToReturn != null) { return objectToReturn; } else { for (BeanDefinition definition : preparedComponents.values()) { if (Arrays.asList(definition.getClazz().getInterfaces()).contains(clazz)) { if (objectToReturn == null) { objectToReturn = definition.getInstance(); } else { throw new FailureComponentCreationException( "Can't resolve component to return, more than one component found, for class: " + clazz.getName()); } } } if (objectToReturn != null) { return objectToReturn; } else { throw new ComponentNotFoundException("Can't find component for class: " + clazz.getName()); } } }
private BeanDefinition findBeenByClass(Class<?> clazz) { BeanDefinition definitionToReturn = beans.get(clazz.getName()); if (definitionToReturn != null) { return definitionToReturn; // TODO Resolve more than one bean to inject bug in this case } else { for (BeanDefinition definition : beans.values()) { if (Arrays.asList(definition.getClazz().getInterfaces()).contains(clazz)) { if (definitionToReturn == null) { definitionToReturn = definition; } else { throw new FailureBeanInjectionException( "Can't resolve bean injection, more than one beanDefinition found, for class: " + clazz.getName()); } } } if (definitionToReturn != null) { return definitionToReturn; } else { throw new FailureBeanInjectionException( "Can't find bean to inject for class: " + clazz.getName()); } } }
/** Creates new bean instance and performs constructor injection. */ protected Object newBeanInstance(BeanDefinition def, Map<String, Object> acquiredBeans) { if (def.ctor == null) { def.ctor = petiteResolvers.resolveCtorInjectionPoint(def.type); } // other ctors if (def.name != null) { acquiredBeans.put(def.name, Void.TYPE); // puts a dummy marker for cyclic dependency check } int paramNo = def.ctor.references.length; Object[] args = new Object[paramNo]; // wiring if (def.wiringMode != WiringMode.NONE) { for (int i = 0; i < paramNo; i++) { args[i] = getBean(def.ctor.references[i], acquiredBeans); if (args[i] == null) { if ((def.wiringMode == WiringMode.STRICT)) { throw new PetiteException( "Wiring constructor failed. References '" + Convert.toString(def.ctor.references[i]) + "' not found for constructor: " + def.ctor.constructor); } } } } // create instance Object bean; try { bean = def.ctor.constructor.newInstance(args); } catch (Exception ex) { throw new PetiteException( "Failed to create new bean instance '" + def.type.getName() + "' using constructor: " + def.ctor.constructor, ex); } if (def.name != null) { acquiredBeans.put(def.name, bean); } return bean; }
/** Wires methods. */ protected void wireMethods(Object bean, BeanDefinition def, Map<String, Object> acquiredBeans) { if (def.methods == null) { def.methods = petiteResolvers.resolveMethodInjectionPoint(def.type); } for (MethodInjectionPoint methodRef : def.methods) { String[][] refNames = methodRef.references; Object[] args = new Object[refNames.length]; for (int i = 0; i < refNames.length; i++) { String[] refName = refNames[i]; Object value = null; boolean mixing = petiteConfig.wireScopedProxy || petiteConfig.detectMixedScopes; if (mixing) { BeanDefinition refBeanDefinition = lookupBeanDefinitions(refName); if (refBeanDefinition != null) { value = scopedProxyManager.lookupValue(this, def, refBeanDefinition); } } if (value == null) { value = getBean(refName, acquiredBeans); } args[i] = value; if (value == null) { if ((def.wiringMode == WiringMode.STRICT)) { throw new PetiteException( "Wiring failed. Beans references: '" + Convert.toString(refName) + "' not found for method: " + def.type.getName() + '#' + methodRef.method.getName()); } } } try { methodRef.method.invoke(bean, args); } catch (Exception ex) { throw new PetiteException(ex); } } }
/** Injects all parameters. */ protected void injectParams(Object bean, BeanDefinition def) { if (def.name == null) { return; } if (def.params == null) { def.params = resolveBeanParams(def.name, petiteConfig.getResolveReferenceParameters()); } int len = def.name.length() + 1; for (String param : def.params) { Object value = getParameter(param); String destination = param.substring(len); try { BeanUtil.setDeclaredProperty(bean, destination, value); } catch (Exception ex) { throw new PetiteException( "Unable to set parameter: '" + param + "' to bean: " + def.name, ex); } } }
/** Wires properties. */ protected void wireProperties( Object bean, BeanDefinition def, Map<String, Object> acquiredBeans) { if (def.properties == null) { def.properties = petiteResolvers.resolvePropertyInjectionPoint( def.type, def.wiringMode == WiringMode.AUTOWIRE); } boolean mixing = petiteConfig.wireScopedProxy || petiteConfig.detectMixedScopes; for (PropertyInjectionPoint pip : def.properties) { String[] refNames = pip.references; Object value = null; if (mixing) { BeanDefinition refBeanDefinition = lookupBeanDefinitions(refNames); if (refBeanDefinition != null) { value = scopedProxyManager.lookupValue(this, def, refBeanDefinition); } } if (value == null) { value = getBean(refNames, acquiredBeans); } if (value == null) { if ((def.wiringMode == WiringMode.STRICT)) { throw new PetiteException( "Wiring failed. Beans references: '" + Convert.toString(refNames) + "' not found for property: " + def.type.getName() + '#' + pip.propertyDescriptor.getName()); } continue; } // BeanUtil.setDeclaredProperty(bean, pip.propertyDescriptor.getName(), value); Setter setter = pip.propertyDescriptor.getSetter(true); try { setter.invokeSetter(bean, value); } catch (Exception ex) { throw new PetiteException("Wiring failed", ex); } } // sets if (def.sets == null) { def.sets = petiteResolvers.resolveSetInjectionPoint(def.type, def.wiringMode == WiringMode.AUTOWIRE); } for (SetInjectionPoint sip : def.sets) { String[] beanNames = resolveBeanNamesForType(sip.targetClass); Collection beans = sip.createSet(beanNames.length); for (String beanName : beanNames) { if (beanName.equals(def.name) == false) { Object value = getBean(beanName, acquiredBeans); beans.add(value); } } // BeanUtil.setDeclaredProperty(bean, sip.field.getName(), beans); Setter setter = sip.propertyDescriptor.getSetter(true); try { setter.invokeSetter(bean, beans); } catch (Exception ex) { throw new PetiteException("Wiring failed", ex); } } }