春5.xのソース旅26詳細getBean
パラメータ保持部を作成します。
私は2つのファクトリメソッドの例を使用し、実際には、その違いが同じであるか、文句を言うだろう、それは問題では、我々は主にプロセスの作品を分析しません。
まず、パラメータ名パラメータプローブの名前は、実際には、内部が取りに行くASM
動作するように読み取り、バイトコード、主にLocalVariableTableParameterNameDiscoverer
読み込むためのクラス、バイナリストリームclass
ファイルを、その後、より複雑な分析が、興味を持って見ることができます。直接のコア上の私たちの分析方法。
createArgumentArray
一般的なケースを残して、含まれていないxml
、手動で設定された設定モード又はパラメータの値をConstructorArgumentValues
それが最も一般的な形態です。パラメータを横断するパラメータの数、これはインデックス・パラメータ含むであろうparamIndex
問題を、xml
そこファクトリメソッド(コンストラクタ)、まず、使用及び共通インデックスにパッケージされるMethodParameter
治療のタイプ、自動組立に続いて、パラメータオブジェクトを解析、最後には登録して依存依存していることをしながら、と言われた非常に複雑であり、bean
実際には、キャッシング、次は直接使用することができます。
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
//类型转换器
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);//参数持有器
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);//构造器参数值集合
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);//装配的bean名字
//带参数的话
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");//获取参数名字
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
...
}
if (valueHolder != null) {
...
}
else {
//获取统一的方法参数类型
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
if (!autowiring) {
throw new UnsatisfiedDependencyException(
...
}
try {//解析自动装配参数,找到会进行实例化
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
//注册依赖的bean
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
パラメータMethodParameter forExecutableをパッケージングする方法
これは、後に一体容易にするために、一緒に一般的な形態にメソッドやコンストラクタのためのプロセスプラントです。
public static MethodParameter forExecutable(Executable executable, int parameterIndex) {
if (executable instanceof Method) {
return new MethodParameter((Method) executable, parameterIndex);
}
else if (executable instanceof Constructor) {
return new MethodParameter((Constructor<?>) executable, parameterIndex);
}
else {
throw new IllegalArgumentException("Not a Method/Constructor: " + executable);
}
}
MethodParameterコンストラクタ
実際には、のようなネストされた層があり、方法およびインデックスセットlist
ネストされた中list
、一時的にコントロールしていないが、これは、我々はまだ一般によると、ネストがある層であり1
、そうでない場合は1
、埋め込ま見つけるために戻って中に入りますセットタイプ。
public MethodParameter(Method method, int parameterIndex, int nestingLevel) {
Assert.notNull(method, "Method must not be null");
this.executable = method;
this.parameterIndex = validateIndex(method, parameterIndex);
this.nestingLevel = nestingLevel;
}
分析パラメータ自動組立resolveAutowiredArgument
まず、注入ポイントタイプか否かが判定されるInjectionPoint
、このタイプの方法が記載されている、またはコンストラクタパラメータまたは属性、これらの場所であるので、自動的に注入することができます。もしそうなら、それは注入点への直接アクセスを返すか、聞かせてbeanFactory
解決の依存関係に、その前に、最初にMethodParameter
カプセル化されDependencyDescriptor
、それは、注入点です。
protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
Class<?> paramType = param.getParameterType();
if (InjectionPoint.class.isAssignableFrom(paramType)) {//是否是注入点类型,比如DependencyDescriptor
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
throw new IllegalStateException("No current InjectionPoint available for " + param);
}
return injectionPoint;
}
try {//beanFactory解析依赖
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
catch (NoUniqueBeanDefinitionException ex) {
throw ex;
}
catch (NoSuchBeanDefinitionException ex) {
if (fallback) {
...
}
throw ex;
}
}
DefaultListableBeanFactory的resolveDependency
判決は当然のことながら、私たちは確かな状況の最後の種類、当社のカスタムタイプ、すぐに呼び出していない場合は、もし遅延ロードを参照されている、さまざまなタイプを処理するために、どのような種類に依存してdoResolveDependency
解決します。
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//设置参数名字探索器
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {//Optional类型
return createOptionalDependency(descriptor, requestingBeanName);
}//是对象工厂类型或者对象提供者类型
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}//java扩展的注入类
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {//我们自己只能的类型,先看是否是懒加载,是的话就直接返回,否则要去解析依赖
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
getDependencyTypeの種類に依存し得るMethodParameter
プロパティがある場合には存在し、ネストされた型よりも大きくなる1
ような実数型、見つけるなりList<String>
、これをString
巣があり2
、本当のタイプはStringです。もちろん、我々は、プロパティの注射ではありませんので、直接呼び出しMethodParameter
のgetNestedParameterType
。
public Class<?> getDependencyType() {
if (this.field != null) {
if (this.nestingLevel > 1) {
Type type = this.field.getGenericType();
for (int i = 2; i <= this.nestingLevel; i++) {
if (type instanceof ParameterizedType) {
Type[] args = ((ParameterizedType) type).getActualTypeArguments();
type = args[args.length - 1];
}
}
if (type instanceof Class) {
return (Class<?>) type;
}
else if (type instanceof ParameterizedType) {
Type arg = ((ParameterizedType) type).getRawType();
if (arg instanceof Class) {
return (Class<?>) arg;
}
}
return Object.class;
}
else {
return this.field.getType();
}
}
else {
return obtainMethodParameter().getNestedParameterType();
}
}
MethodParameter的getNestedParameterType
私は、一層のみが存在する場合、それは直接呼び出され、処理ロジックは同じ属性ほとんどで、実際には、重複したコードの多くを発見しましたgetParameterType
。
public Class<?> getNestedParameterType() {
if (this.nestingLevel > 1) {
Type type = getGenericParameterType();
for (int i = 2; i <= this.nestingLevel; i++) {
if (type instanceof ParameterizedType) {
Type[] args = ((ParameterizedType) type).getActualTypeArguments();
Integer index = getTypeIndexForLevel(i);
type = args[index != null ? index : args.length - 1];
}
// TODO: Object.class if unresolvable
}
if (type instanceof Class) {
return (Class<?>) type;
}
else if (type instanceof ParameterizedType) {
Type arg = ((ParameterizedType) type).getRawType();
if (arg instanceof Class) {
return (Class<?>) arg;
}
}
return Object.class;
}
else {
return getParameterType();
}
}
DependencyDescriptor的getNestedParameterType
ダイレクト戻り値の型、または他の処理は、パラメータの型を取得するために行われますがあります。
public Class<?> getParameterType() {
Class<?> paramType = this.parameterType;
if (paramType != null) {
return paramType;
}
if (getContainingClass() != getDeclaringClass()) {
paramType = ResolvableType.forMethodParameter(this, null, 1).resolve();
}
if (paramType == null) {
paramType = computeParameterType();
}
this.parameterType = paramType;
return paramType;
}
さて、今日ここに、私たちは自分自身の学習、限られた容量を理解し、偉大な神は見スプレーしないで、言い訳してください、助けの調査に希望と理解しています。