@Autowired Роль аннотаций в Spring заключается в реализации внедрения зависимостей (Dependency Injection), который используется для автопроводки Spring Bean зависимости. Конкретно, @Autowired Аннотации имеют следующие функции:
Наиболее важными концепциями Spring Framework являются IoC и DI. Благодаря этим двум функциям платформа может управлять зависимостями между объектами, создавать зависимости между объектами, а зависимые объекты можно автоматически внедрять в классы, которые в них нуждаются. При их использовании нет необходимости вручную создавать или находить зависимые объекты. Основные методы внедрения зависимостей следующие:
Независимо от того, какой метод инъекции,Spring получит элементы конфигурации компонента (определение компонента и зависимости).,Затем я проанализирую это на уровне исходного кода.@Autowired
Процесс внедрения зависимостей。
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//Пропускаем другие коды и показываем основной процесс
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
создаватьBeanОсновная логика метода заключается в следующем.doCreateBean
середина,Spring FrameworkпроходитьdoCreateBean
создавать指定Bean,В методе середина,ЧтосерединапроходитьpopulateBean()
Обход соответствующего постпроцессора,То есть: когда класс, отмеченный аннотацией, вводится в контейнер Spring.,Сначала будет создан объект Bean.,создавать后调用populateBean
方法以遍历后置处理器проходить后置处理器获取到需要изvalue,Воля@Autowired
аннотациясерединаизсвойство(Юаньданные)назначен наBeanсередина。
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
//InstantiationAwareBeanPostProcessors может обеспечить постобработку для @Autowiredаннотации,
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//Обходим все связанные постпроцессоры и получаем необходимое значение
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
@Autowired
аннотация所需из后置处理器是:AutowiredAnnotationBeanPostProcessor
。СледующийSpring容器开始использовать该аннотацияиз后置处理器去获取对应изсвойствоvalue,Предположим, мы не знаем логику @Autowiredаннотации, соответствующей постпроцессору.,Затем, исходя из этого требования, угадайте имя метода соответствующей логики постпроцессора: у него должна быть обработка и атрибуты.,Тогда соответствующие слова: Процесс, Свойства.,Найдите соответствующий,postProcessProperties()
это целевой метод。
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//По данным BeanNameПолучить внедренные метаданные
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//Элемент dataValue вводится в целевой Beanсередина
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
//Используется для кэширования данных элементов Bean, анализируемых Spring
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Запросить, существуют ли соответствующие данные элемента в кеше середина-Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//Когда кеш середина не содержит метаданных указанного компонента, создаем метаданные
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
Spring FrameworkпроходитьbuildAutowiringMetadata()
Метод анализааннотациясерединаизданные。
//Комбинация аннотаций, которую необходимо разобрать
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.
* для Spring Создайте новый AutowiredAnnotationBeanPostProcessor для стандартных аннотаций @Autowired и @Value.
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
Этот код сначала вызовет isCandidateClass
Метод определяет, является ли текущий класс классом-кандидатом. Основанием для принятия решения является. добрый、свойство、Содержит ли методautowiredAnnotationTypes
собиратьсередина初始化из值(@Autowired
、@Value
、@Inject
),Когда определение середина Bean содержит множество середина соответствующего типа аннотация,судитьдля候选добрый,Затем получите данные элемента, соответствующие аннотациисередина для этого класса.
Если Bean середина не имеет указанного типа аннотации,Возвращает пустой объект Внедрение метаданных. Если указана аннотация,Затем начните получать данные аннотациисередина в юанях.
Способ получения метаданных — через отражение. Ниже представлена логика получения соответствующих аннотаций в классах, свойствах и методах посредством отражения.
Возьмем в качестве примера DruidDataSourceWrapper:
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//Получить атрибуты в полях указанного класса посредством отражения
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
}
Возьмем DruidDataSource в качестве примера.
//Получить атрибуты в методе указанного класса посредством отражения.
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
AutowiredAnnotationBeanPostProcessor
добрыйсерединаизinject
方法用来注入Юаньданные。
Этот метод сначала получит данные элемента из кэша середина.,Если кэш середина не работает,затем выполнитеresolvedCachedArgument
Анализ значения поля。
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
@Nullable
private ConfigurableListableBeanFactory beanFactory;
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
//Разбираем основной метод
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
DependencyDescriptor: представляет и обрабатывает зависимости между компонентами Bean.
resolveDependency
Метод — это интерфейсBeanFactory接口提供из,DefaultListableBeanFactory — это класс реализации BeanFactory.
resolveDependency
Методы анализа и разрешения зависимостей,Функция этого метода основана на данном объекте DependencyDescriptor.,Разбирать и возвращать зависимые объекты разных типов,Нынешний подход в конечном итоге исчезнет.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()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
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;
}
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
Выше список объектов-кандидатов, соответствующих условиям, заполнен и введен.