Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.jvault.vault;
import org.jvault.annotation.Inject;
import org.jvault.annotation.InternalBean;
import org.jvault.bean.Bean;
import org.jvault.bean.Type;
import org.jvault.exceptions.DisallowedAccessException;
import org.jvault.exceptions.NoDefinedInternalBeanException;
import org.jvault.factory.extensible.Vault;
import org.jvault.metadata.API;
import org.jvault.metadata.ThreadSafe;
import org.jvault.util.Reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Receive the Class type as a parameter and returns the corresponding instance.
*
* ClassVault injects beans into parameters, using the @Inject annotation mapped to a field or constructor of the parameter's class.
* Examples.
*
*
* 1. Field Inject
*
* {@code
* public class Foo { @Inject private SomeBean bean; }
* }
*
* If a Foo.class is passed to a method of ClassVault,
* First, ClassVault creates an instance of Foo.class using default constructor and injects the bean into the field marked with @Inject.
* After that, by the above process, the instance of Foo into which the bean is injected is returned.
*
* 2. Constructor Inject
*
* If a Foo.class is passed to a method of ClassVault,
* First, ClassVault creates an instance of Foo.class using the @Inject mapped constructor.
* In this process, the bean is passed as a parameter of the @Inject marked constructor,
* and finally the instance of Foo.class into which the bean is injected is returned.
* If a class has more than one @Inject marked constructor, a DuplicateConstructorException is thrown.
* If there is a parameter that is not mapped to @Inject in the parameter of the constructor mapped to @Inject, an IllegalStateException is thrown.
*
* ClassVault can only be instantiated in the org.jvault.* package,
* and actually you can't force instantiation of Vault without using Reflection.
* To obtain ClassVault, see the {@link org.jvault.factory.TypeVaultFactory} class.
*
* @author devxb
* @see org.jvault.factory.TypeVaultFactory
* @see Vault
* @see org.jvault.annotation.Inject
* @see org.jvault.annotation.InternalBean
* @since 0.1
*/
@API
@ThreadSafe
public final class ClassVault extends AbstractVault> {
private final ConcurrentMap, Bean> CACHED_BEANS;
private final Reflection REFLECTION;
ClassVault(Vault.Builder builder) {
super(builder);
CACHED_BEANS = new ConcurrentHashMap<>();
REFLECTION = Accessors.UtilAccessor.getAccessor().getReflection();
}
/**
* Same method as inject(injectTarget, returnType).
* The inject(injectTarget, returnType) method receives two parameters to prevent unchecked cast,
* but this method enables the above function to be performed with one parameter.
* Therefore, it is more convenient and recommended to use this method.
*
* @param type The class-type of target to be injected beans, Vault will inject beans into this parameter.
* @return Returns an instance of the type received param.
* @param the type of return instance.
*/
public R inject(Class type){
return inject(type, type);
}
/**
* Method of inject beans into class-type-parameter and return instance of class-type-parameter.
*
* If parameter was mapped to @InternalBean(type = Type.SINGLETON) and included in the scope of Vault's bean scan,
* ClassVault caches this parameter and returns the cached instance from the next request.
*
* @param the type of return instance.
* @param injectTarget The class-type of target to be injected beans, Vault will inject beans into this parameter.
* @param returnType The class-type to be returned. This must be a type that matches the param parameter.
* @return Returns an instance of the injectTarget received param.
* @throws DisallowedAccessException Occurs when the package in param is a package that does not have access to Vault,
* * or the Beans to be injected into param cannot be injected into the package in Param.
*/
@Override
public R inject(Class> injectTarget, Class returnType) {
throwIfParamDoesNotAccessible(injectTarget);
if(CACHED_BEANS.containsKey(injectTarget)) return CACHED_BEANS.get(injectTarget).loadIfInjectable(injectTarget);
cacheBean(injectTarget);
if(CACHED_BEANS.containsKey(injectTarget)) return CACHED_BEANS.get(injectTarget).loadIfInjectable(injectTarget);
Constructor> constructor = REFLECTION.findConstructor(injectTarget);
if (constructor != null) return returnType.cast(loadBeanFromConstructor(injectTarget, constructor));
List fields = REFLECTION.findFields(injectTarget);
return returnType.cast(loadBeanFromField(injectTarget, fields));
}
@SuppressWarnings("all")
private void cacheBean(Class> cls){
if(isDoseNotNeedCache(cls)) return;
String cachedBeanName = getBeanName(cls);
synchronized (cls) {
if (BEANS.containsKey(cachedBeanName)) CACHED_BEANS.put(cls, BEANS.get(cachedBeanName));
}
}
private boolean isDoseNotNeedCache(Class> cls){
InternalBean internalBean = cls.getDeclaredAnnotation(InternalBean.class);
return internalBean == null || internalBean.type() != Type.SINGLETON;
}
private String getBeanName(Class> cls) {
String name = convertToBeanName(cls.getSimpleName());
InternalBean internalBean = cls.getDeclaredAnnotation(InternalBean.class);
if (internalBean.name().equals("")) return name;
return internalBean.name();
}
private String convertToBeanName(String name) {
return name.substring(0, 1).toLowerCase() + name.subSequence(1, name.length());
}
private Object loadBeanFromConstructor(Class> cls, Constructor> constructor) {
List parameters = REFLECTION.getAnnotatedConstructorParameters(constructor);
List