Yay kaynak kodu öğrenme (1) -konteyner altyapısı

Yaratıcı JingQ Java Geek Technology

Görüntülenen kod bazı temel yöntemleri çıkarır, bazı varsayılan ayarları ve günlük çıktısını kaldırır ve ayrıca hata istisnalarının çoğunu kaldırır.Ayrıntılı kodu, yorumları ve demoları görmek istiyorsanız, yüklediğim not projesini indirebilirsiniz.

Code Cloud Gitee adresi https://gitee.com/vip-augus/spring-analysis-note.git

Github adresi https://github.com/Vip-Augus/spring-analysis-note

Kaynak kodunu okuma sürecinde, tasarımcının tasarım fikirlerini anlayın ve ondan öğrenin ve temel bir bahar anlayışına sahip olun.

ClassPathXmlApplicationContext

ClassPathXmlApplicationContext'in miras mimarisi diyagramı:

Bu tür bir yapı diyagramı, IDEA düzenleyicisinin Diyagramlar işlevi aracılığıyla görüntülenir. Geçerli sınıfa sağ tıklayın ve kalıtım sistemini, hangi sınıfların miras alındığını ve hangi arabirimlere başvurulduğunu görebilirsiniz, böylece anlayabiliriz ~

ClassPathXmlApplicationContext, AbstractApplicationContext'ten miras alır ve AbstractRefreshableApplicationContext, AbstractApplicationContext'in soyut bir alt sınıfıdır. Kullanılan sınıf kayıt fabrikası DefaultListableBeanFactory'dir. Bu kayıt fabrikası da çok önemlidir ve daha sonra tanıtılacaktır.

Basitçe söylemek gerekirse, DefaultListableBeanFactory, Spring'in fasulye kaydı ve yüklemesinin varsayılan uygulamasıdır.Kayıtlı çekirdekleri anahtar-değer depolaması için beanDefinitionMap'e koyar.

Resmin sağ üst köşesinde görebileceğiniz gibi, ResourceLoader, bu sınıfın kaynak yükleme işlevini uyguladığını gösteren üst düzey arayüzüdür.

Yapıcının kodu:

genel ClassPathXmlApplicationContext (

String configLocations, boolean yenileme, @Nullable ApplicationContext parent)

BeansException {atar

süper (ebeveyn);

// Not 1.1 Kaynak dosyalarını alın

setConfigLocations (configLocations);

eğer (yenile) {

yenileme ();

}

}

Yapılandırma dosyası yolunu ayarlayın

org.springframework.context.support.AbstractRefreshableConfigApplicationContext

public void setConfigLocations (@Nullable String ... konumlar) {

eğer (konumlar! = boş) {

Assert.noNullElements (konumlar, "Yapılandırma konumları boş olmamalıdır");

// Not 1.2 Yapılandırma kaynak yolunu configLocations dizisine yerleştirin

this.configLocations = new String;

for (int i = 0; i < konumlar.length; i ++) {

this.configLocations = resolPath (konumlar ) .trim ();

}

}

Başka {

this.configLocations = null;

}

}

SolutionPath'in amacı şudur: Verilen yolu ayrıştırın ve yer tutucuyu karşılık gelen yer tutucuyla değiştirin

Örneğin, yeni ClassPathXmlApplicationContext ("classpath: config.xml");, sınıf yolunu ayrıştırmanız ve doğru yola çevirmeniz gerekir.

korumalı Dize resolverPath (Dize yolu) {

getEnvironment (). returnRequiredPlaceholders (yol);

}

Geliştirme, test veya üretim gibi farklı işletim ortamlarımız var. Şu anda yüklenen yapılandırma dosyaları ve özellikler farklı olmalıdır. Şu anda, ayırt etmek için Ortamı kullanmamız gerekiyor.

Yay ortamı ve özellikleri dört bölümden oluşur:

  • Environment: Environment, Profile ve PropertyResolver'ın bir kombinasyonu.
  • Profil: Kapsayıcıdaki birden çok yapılandırma grubunun öznitelikleri ve çekirdekleri olarak anlaşılabilecek yapılandırma dosyası. Yalnızca etkin profil, ilgili grup öznitelikleri ve fasulye yüklenir
  • PropertySource: Özellik kaynağı, özellikleri anahtar-değer biçiminde depolamak için CopyOnWriteArrayList dizisini kullanın
  • PropertyResolver: Özellik çözümleyici, bu amaç özellikleri çözümlemektir

Profil

Bu öznitelik aracılığıyla, yapılandırma dosyasında aynı anda iki yapılandırma kümesi dağıtılabilir; bu, üretim ortamı ve geliştirme ortamı için uygundur, böylece geliştirme ve dağıtım ortamını değiştirmek uygun olur ve genellikle farklı veritabanları veya yapılandırma dosyalarını değiştirmek için kullanılır.

demo: (referans 4'ten alıntılanmıştır)

< ! - Test ortamı yapılandırma dosyası - >

< fasulye profili = "test" >

< bağlam: özellik-yer tutucu location = "sınıf yolu: test / *. özellikler, sınıf yolu: ortak / *. özellikler" / >

< /Fasulyeler >

< ! - Üretim ortamı yapılandırma dosyası - >

< fasulye profili = "üretim" >

< bağlam: özellik-yer tutucu location = "sınıf yolu: üretim / *. özellikler, sınıf yolu: ortak / *. özellikler" / >

< /Fasulyeler >

< ! - Geliştirme ortamı yapılandırma dosyası - >

< fasulye profili = "geliştirme" >

< bağlam: özellik-yer tutucu location = "sınıf yolu: dev / *. özellikler, sınıf yolu: ortak / *. özellikler" / >

< /Fasulyeler >

Hangi yapılandırmanın kullanılacağını seçmenin iki yolu vardır:

web.xml'de ayarlayın

< bağlam parametresi >

< param-adı > spring.profiles.active < / param-adı >

< param-değeri > Ölçek < / param-değeri >

< / context-param >

Kodun ne zaman başlayacağını ayarlayın

context.getEnvironment (). setActiveProfiles ("test");

PropertySource arayüzü

Miras sistemi şekilde gösterilmiştir:

PropertySource miras sistemi perspektifinden, customPropertySources yönteminin çağrı bağlantısı, alt sınıftan sonuna kadar çağırmaktır:

SoyutÇevre > StandardServletEnvironment- > StandardEnvironment

Son olarak, öznitelik depolaması için StandardEnvironment'daki CopyOnWriteArrayList dizisini kullanın

korumalı void customPropertySources (MutablePropertySources propertySources) {

propertySources.addLast (yeni MapPropertySource (SYSTEM_PROPERTYES_PROPERTY_SOURCE_NAME, getSystemProperties ()));

propertySources.addLast (yeni SystemEnvironmentPropertySource (SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment ()));

}

Örneğin, yukarıdan da görülebileceği gibi, propertySourceList sistem parametrelerini saklayacaktır:

Daha sonra bu parametreler, bağlam bağlamı aracılığıyla başlatılan uygulamada elde edilebilir

((MutablePropertySources) ((StandardEnvironment) context.environment) .propertySources) .propertySourceList

Fasulye analizi ve kaydı

Bahar fasulyesi ayrıştırma ve kaydı önemli bir yöntem yenileme ()

AbstractApplicationContext.refresh ()

public void refresh (), BeansException, IllegalStateException {atar

senkronize (this.startupShutdownMonitor) {

// Bu bağlamı yenileme için hazırlayın. (Güncellemeye bağlam hazırlayın, bazı işaretler ayarlayın)

hazırlamakRefresh ();

// Alt sınıfa dahili fasulye fabrikasını yenilemesini söyleyin. (Alt sınıfa dahili fasulye fabrikasını yenilemesini söyleyin)

// Fasulye fabrikasına sınıfın kaydı da bu aşamada

YapılandırılabilirListableBeanFactory beanFactory = eldeFreshBeanFactory ();

// Fasulye fabrikasını bu bağlamda kullanmak için hazırlayın.

hazırlamakBeanFactory (beanFactory);

Deneyin {

// Fasulye fabrikasının bağlam alt sınıflarında sonradan işlenmesine izin verir.

postProcessBeanFactory (beanFactory);

// Bağlamda fasulye olarak kaydedilmiş fabrika işlemcilerini çağırın.

invokeBeanFactoryPostProcessors (beanFactory);

// Fasulye oluşumunu engelleyen fasulye işlemcilerini kaydedin.

registerBeanPostProcessors (beanFactory);

// Bu bağlam için mesaj kaynağını başlatın.

initMessageSource ();

// Bu bağlam için olay çok yöneticisini başlatın.

initApplicationEventMulticaster ();

// Belirli bağlam alt sınıflarında diğer özel fasulyeleri başlatın.

onRefresh ();

// Dinleyici çekirdeklerini kontrol edin ve kaydedin.

registerListeners ();

// Kalan tüm (tembel olmayan) tekilleri örnekleyin.

finishBeanFactoryInitialization (beanFactory);

// Son adım: karşılık gelen etkinliği yayınlayın.

finishRefresh ();

}

catch (BeansException ex) {

if (logger.isWarnEnabled ()) {

logger.warn ("Bağlam başlatma sırasında karşılaşılan istisna -" +

"yenileme girişiminin iptal edilmesi:" + örn);

}

// Kaynakların sarkmasını önlemek için önceden oluşturulmuş tekilleri yok edin.

destroyBeans ();

// 'Etkin' işaretini sıfırlayın.

cancelRefresh (eski);

// İstisnayı çağırana ilet.

eski atmak;

}

en sonunda {

// Spring'in çekirdeğindeki yaygın iç gözlem önbelleklerini sıfırlayın, çünkü

// artık tekli çekirdekler için meta veriye ihtiyaç duymayabilir ...

resetCommonCaches ();

}

}

}

Aşağıda, izleme ve analiz için bu yönteme odaklanılacaktır.

Belirli doğrulama yöntemi

org.springframework.core.env.AbstractPropertyResolver # validateRequiredProperties

public void validateRequiredProperties () {

MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException ();

for (String key: this.requiredProperties) {

eğer (this.getProperty (key) == null) {

ex.addMissingRequiredProperty (anahtar);

}

}

eğer (! ex.getMissingRequiredProperties (). isEmpty ()) {

eski atmak;

}

}

Gördüğünüz gibi, doğrulama mantığı, varsayılan olarak boş olan bir karakter kümesi olan requiredProperties'i geçmek içindir, bu, hiçbir elemanın doğrulanması gerekmediği anlamına gelir.Listede bir değer varsa, boş olacak anahtara göre karşılık gelen ortam değişkenini alın. Bahar kapsayıcısının başlatılamamasına neden olan bir istisna atıldı.

Fasulye kabını alın

Bu kod satırında ConfigurableListableBeanFactory beanFactory = findFreshBeanFactory ();

Spesifik çağrı şudur:

org.springframework.context.support.AbstractRefreshableApplicationContext # renewBeanFactory

korumalı son void refreshBeanFactory () BeansException {

// Güncelleme sırasında zaten var olduğu tespit edilirse önceki çekirdek temizlenecek ve eski çekirdek kabı kapatılacaktır.

eğer (hasBeanFactory ()) {

destroyBeans ();

closeBeanFactory ();

}

Deneyin {

DefaultListableBeanFactory beanFactory = createBeanFactory ();

beanFactory.setSerializationId (getId ());

customBeanFactory (beanFactory);

// Yorum 1.3 yüklemeye başlar (fasulye kaydı)

loadBeanDefinitions (beanFactory);

senkronize (this.beanFactoryMonitor) {

this.beanFactory = beanFactory;

}

}

catch (IOException ex) {

yeni ApplicationContextException ("I / O hatası için fasulye tanımı kaynağını ayrıştırırken" + getDisplayName (), örn.);

}

}

Bu giriş yöntemi çok önemlidir Bu adımda, yeni bir fasulye kabı ve ayrıştırılmış bir çekirdek oluşturulur ve çekirdek kabın içine kaydedilir.

BanFactory özel

Spesifik yöntem aşağıdaki gibidir: Bu yöntemle fabrika özelleştirilebilir ve alt sınıflar serbestçe yapılandırılabilir:

org.springframework.context.support.AbstractRefreshableApplicationContext # customBeanFactory

korumalı void customBeanFactory (DefaultListableBeanFactory beanFactory) {

eğer (this.allowBeanDefinitionOverriding! = null) {

// Varsayılan yanlıştır, üzerine yazmaya izin verilmez

beanFactory.setAllowBeanDefinitionOverriding (this.allowBeanDefinitionOverriding);

}

eğer (this.allowCircularReferences! = null) {

// Varsayılan yanlıştır, döngüsel referanslara izin verilmez

beanFactory.setAllowCircularReferences (this.allowCircularReferences);

}

}

EntityResolver

Arayüzün tam yolu şudur: org.xml.sax.EntityResolver, analiz için kullanılan özel yöntem şudur:

org.springframework.beans.factory.xml.ResourceEntityResolver # resolEntity

Bu yöntem, şema ve dtd'yi ayrıştırmak için kullanılır. Daha derine inerseniz çok karmaşıktır, ancak xml ayrıştırmak benim anlamak istediğim şey değildir, bu yüzden önce atlayın ~

Yapılandırma dosyası yükleniyor

Giriş yöntemi: (Aynı ada sahip birden fazla yöntem olduğundan, yolu kopyalarken parametre türü de kopyalanır)

org.springframework.beans.factory.support.AbstractBeanDefinitionReader # loadBeanDefinitions (java.lang.String, java.util.Set < org.springframework.core.io.Resource > )

Temel yöntem bu iki satırdır

public int loadBeanDefinitions (Dize konumu, @Nullable Set < Kaynak > realResources), BeanDefinitionStoreException {

// Kaynak dosyasını alın (kaynak yükleyici, kaynak dosyasını yoldan tanımlar)

Kaynak kaynakları = ((ResourcePatternResolver) resourceLoader) .getResources (konum)

// Not 1.6 Fasulyeyi kaynak dosyasına göre yükleyin

int count = loadBeanDefinitions (kaynaklar);

···

}

Kaynak dosyasını aldıktan sonra, kaynak dosyasını (yani başlangıçta iletilen config.xml) ayrıştırmaya başlayın ve bunu Belgeye dönüştürün

İzleme kodundan, ayrıştırılacak kaynak dosyasının Resource'tan EncodeResouce'a paketlendiğini ve karakter kodlamasının, tasarım deseni dekoratör modunu yansıtan giriş akışına eklendiğini (varsayılan değer boştur) görebilirsiniz.

Kaynak dosyasında gezinmek ve dönüştürme gerçekleştirmek için temel yöntem aşağıdaki iki satırdır:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader # loadBeanDefinitions (org.springframework.core.io.support.EncodedResource)

public int loadBeanDefinitions (EncodedResource encodedResource) BeanDefinitionStoreException {

// Not 1.7 Kaynak dosyadan giriş akışını alın

InputStream inputStream = encodedResource.getResource (). GetInputStream ();

InputSource inputSource = yeni InputSource (inputStream);

dönüş doLoadBeanDefinitions (inputSource, encodedResource.getResource ());

}

Varsayılan etiket çözünürlüğü

Bu bölüm ayrıntılara girmeyecek ve daha sonra onu tamamlamak için bir makale yazacağım, bu yüzden koddaki varsayılan etiketin nasıl ayrıştırılacağına bakacağım.

  • İTHALAT: Etiketleri içe aktarın
  • ALIAS: Takma ad etiketi
  • FASULYE: fasulye etiketi
  • NESTED_BEANS: fasulye etiketi (iç içe geçmiş fasulye)
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader # parseDefaultElement

private void parseDefaultElement (Element ele, BeanDefinitionParserDelegate delegate) {

eğer (delegate.nodeNameEquals (ele, IMPORT_ELEMENT)) {

importBeanDefinitionResource (ele);

}

else if (delegate.nodeNameEquals (ele, ALIAS_ELEMENT)) {

processAliasRegistration (ele);

}

else if (delegate.nodeNameEquals (ele, BEAN_ELEMENT)) {

processBeanDefinition (ele, delege);

}

else if (delegate.nodeNameEquals (ele, NESTED_BEANS_ELEMENT)) {

// yineleme

doRegisterBeanDefinitions (ele);

}

}

Bakalım fasulye etiketlerinin nasıl ayrıştırılacağı

Kimliği ve adı alın

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate # parseBeanDefinitionElement (org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

public BeanDefinitionHolder parseBeanDefinitionElement (Element ele, @Nullable BeanDefinition containsBean) {

// ID özniteliğini al

Dize kimliği = ele.getAttribute (ID_ATTRIBUTE);

// NAME özelliğini al

String nameAttr = ele.getAttribute (NAME_ATTRIBUTE);

Liste < Dize > aliases = new ArrayList < > ();

if (StringUtils.hasLength (nameAttr)) {

// İsim,;

String nameArr = StringUtils.tokenizeToStringArray (nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);

aliases.addAll (Arrays.asList (nameArr));

}

String beanName = id;

eğer (! StringUtils.hasText (beanName)! aliases.isEmpty ()) {

// id belirtilmezse, id olarak ismin ilk değerini kullanın

beanName = takma adlar.remove (0);

}

// varsayılan boş

if (containsBean == null) {

// Adın benzersiz olup olmadığını kontrol edin, kimlik tekrarlanırsa bir hata atılır

// Internal usedNames, yüklenen adı ve takma adları depolayan bir HashSet'tir

checkNameUniqueness (beanName, takma adlar, ele);

}

// public özelliğini, GenericBeanDefinition alt sınıfında uygulanan AbstractBeanDefinition içine koyun

AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement (ele, beanName, includingBean);

eğer (beanDefinition! = null) {

eğer (! StringUtils.hasText (beanName)) {

eğer (containsBean! = null) {

// id ve adın her ikisi de boşsa, bu yay onun için varsayılan bir ad oluşturacaktır

beanName = BeanDefinitionReaderUtils.generateBeanName (

beanDefinition, this.readerContext.getRegistry (), true);

}

Başka {

beanName = this.readerContext.generateBeanName (beanDefinition);

String beanClassName = beanDefinition.getBeanClassName ();

eğer (beanClassName! = null

beanName.startsWith (beanClassName) beanName.length () > beanClassName.length ()

! this.readerContext.getRegistry (). isBeanNameInUse (beanClassName)) {

aliases.add (beanClassName);

}

}

}

}

String aliasesArray = StringUtils.toStringArray (takma adlar);

return new BeanDefinitionHolder (beanDefinition, beanName, aliasesArray);

}

boş döndür;

}

Kimlik ve ad özniteliklerini elde etme süreci, kod yorumlarını adım adım takip ederek anlaşılır.

Bu yöntemin ana iş akışı aşağıdaki gibidir:

  • Öğedeki id name özniteliğini ayıklayın
  • Diğer tüm öznitelikleri daha fazla ayrıştırın ve bunları GenericBeanDefinition türünün örneklerinde kapsülleyin
  • Fasulyenin beanName'i belirtmediği tespit edildi, beanName'i varsayılan kuralları kullanarak oluştur
  • Elde edilen bilgileri bir BeanDefinitionHolder örneğinde kapsülleyin

Etiketteki diğer özelliklerin analizi

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate # parseBeanDefinitionElement (org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)

public AbstractBeanDefinition parseBeanDefinitionElement (

Eleman ele, String beanName, @Nullable BeanDefinition containsBean) {

AbstractBeanDefinition bd = createBeanDefinition (sınıfAdı, üst);

parseBeanDefinitionAttributes (ele, beanName, includeBean, bd);

bd.setDescription (DomUtils.getChildElementValueByTagName (ele, DESCRIPTION_ELEMENT));

parseMetaElements (ele, bd);

parseLookupOverrideSubElements (ele, bd.getMethodOverrides ());

parseReplacedMethodSubElements (ele, bd.getMethodOverrides ());

parseConstructorArgElements (ele, bd);

parsePropertyElements (ele, bd);

parseQualifierElements (ele, bd);

bd.setResource (this.readerContext.getResource ());

bd.setSource (extractSource (ele));

dönüş bd;

}

Bu yöntemde BeanDefiniton'ı başlatın: (Spesifik uygulama, alt sınıfı GenericBeanDefinition ~)

BeanDefinitionReaderUtils.createBeanDefinition (parentName, className, this.readerContext.getBeanClassLoader ())

public static AbstractBeanDefinition createBeanDefinition (

@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) ClassNotFoundException {

GenericBeanDefinition bd = new GenericBeanDefinition ();

bd.setParentName (parentName);

eğer (className! = null) {

eğer (classLoader! = null) {

bd.setBeanClass (ClassUtils.forName (className, classLoader));

}

Başka {

bd.setBeanClassName (sınıfAdı);

}

}

dönüş bd;

}

Bir sonraki adım, diğer etiketlerin içeriğini ayrıştırmak ve ardından çukuru oluşturmaktır ~

BeanDefinitionHolder değişikliği

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate # decorateBeanDefinitionIfRequired (org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinitionHolder, org.springframework.beans.factory.config)

public BeanDefinitionHolder decorateBeanDefinitionIfRequired (

Eleman ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containsBd) {

// Yöntemdeki üçüncü parametre, ana fasulyedir

// İç içe yerleştirilmiş bir yapılandırmayı analiz ederken, üst sınıfın kapsam özniteliğini kullanmak için buraya geçirilmesi gerekir, alt sınıfın kapsamı ayarlamaması durumunda, üst sınıfın kapsam özniteliğini kullanabilirsiniz

BeanDefinitionHolder finalDefinition = definitionHolder;

// Önce özel özniteliklere göre dekorasyon yapın.

NamedNodeMap nitelikleri = ele.getAttributes ();

// Tüm nitelikleri çaprazlayın ve nitelikleri değiştirin

for (int i = 0; i < attributes.getLength (); i ++) {

Düğüm düğümü = öznitelikler.item (i);

finalDefinition = decorateIfRequired (node, finalDefinition, containsBd);

}

// Özel iç içe yerleştirilmiş öğelere göre dekorasyon yapın.

NodeList çocukları = ele.getChildNodes ();

// Tüm alt düğümleri geçin ve alt öğeleri değiştirin

for (int i = 0; i < children.getLength (); i ++) {

Düğüm düğümü = children.item (i);

eğer (node.getNodeType () == Node.ELEMENT_NODE) {

finalDefinition = decorateIfRequired (node, finalDefinition, containsBd);

}

}

return finalDefinition;

}

Önceki normal özellik analizinden sonra, bu işlem adımında, esas olarak özel etiket öğelerinin analizini tamamlamak için kullanılır. Burada bir boşluk bırakalım ~

hazırlamakBeanFactory

Sınıf yükleyicinin ortamını hazırlayın ve ClassLoader, post-processors vb. Dahil olmak üzere daha önce elde edilen beanFactory'yi (ConfigurationListableBeanFactory) ayarlayın.

invokeBeanFactoryPostProcessors

Tüm kayıtlı BeanFactoryPostProcessorBeans örneğini oluşturun ve çağırın. Bunlar işlem sonrası işlemcilerdir ve işleme türü BeanFactory'dir. Yay kapsayıcı, çekirdeği başlatmadan önce çekirdek bilgilerini okumanıza ve özelliklerini değiştirmenize olanak tanır.

Kullanıcıya, somutlaştırmadan önce çekirdek bilgisini değiştirmek için son şansı vermeye eşdeğerdir.

Diğer bir nokta da, bu işlemcilerin PriorityOrdered, Order arabirimini uygulayıp uygulamadığına ve sipariş değerine göre sıralamanın sıralı bir sıraya sahip olabilmesidir.

initMessageSource

Bu bağlamın mesaj kaynağını başlatın

onRefresh

Bağlama özgü yenileme çalışması eklemek için şablon yöntemi geçersiz kılınabilir.

Tekliyi somutlaştırmadan önce özel fasulyenin başlatılmasını çağırın. (Sis, özel fasulyenin ne olduğunu bilmiyorum, bir delik bırak = - =)

Bu uygulama boş.

finishBeanFactoryInitialization

Çekirdek kabının başlatılmasını tamamlayın ve kalan tüm (tembel olmayan başlatma) tekilleri somutlaştırın

resetCommonCaches

Önbelleği temizlemek için kullanılan gerçek kaydın son adımıdır

Spring çekirdeğindeki genel iç gözlem önbelleğini sıfırlayın, çünkü artık tekil çekirdeğin meta verilerine ihtiyacımız olmayabilir.

Pit rekoru

Javadoc derleme hatası

Javadoc oluşturma başarısız. Oluşturulan Javadoc seçenekler dosyası (sorun giderme için kullanışlıdır)

Derleme sırasında, başarılı olamadığı ve Javadoc'ta bir hataya yol açtığı bulundu. Çözüm, aşağıdaki yapılandırmayı gradle dosyasına eklemektir:

task.withType (Javadoc) {

options.addStringOption ('Xdoclint: yok', '- sessiz')

options.addStringOption ('kodlama', 'UTF-8')

}

AI Vision, Intel ve Deep Vision Teknolojisi ile Endüstriyel Kalite Denetimi Ortak Röportajından Faydalanıyor
önceki
DJI OSMO ACTON, VLOG dünyanızı yeniden tanımlıyor
Sonraki
PytorchHub'dan daha önce mi? Üç dakika içinde PaddleHub'ı anlamanıza yardımcı olur
2019 Uluslararası Yeni Ekran Teknolojisi Fuarı "Huajia Color Speed" panel endüstrisinde yeni bir fırtına başlattı
"Justin" "Paylaş" 190624 Bugünün yemek çekimi taze! Sporcu Justin güneşin tadını çıkarmak için dışarı çıktı
"GOT7" "Share" 190624 Lam Jae Bum "OFFSHORE" albümünün prodüksiyonuna katıldı, ilk düzenleme çalışması yayınlandı
"NCT" "News" 190624 NCT127, denizaşırı tarifeyi sona erdirir ve Incheon Uluslararası Havaalanı üzerinden Kore'ye varır
Yenilikçi ve profesyonel cazibe Zhiyun sabitleyici, CES Asia 2019'da görücüye çıktı
Dijital mürekkebin gelişimini desteklemek Wacom, CESAsia 2019'da görkemli bir başlangıç yaptı
BOE, DISPLAY CHINA 2019'da yeni ürünlerini tanıttı
Chongqing Huike yeni ürünlerini DISPLAY CHINA 2019'da sunuyor
190624 Wu Yifan'ın Paris Moda Haftası'ndaki son sokak çekimi burada! Sözcü ile Paris sokaklarındaki romantizmi yakalayın
"GOT7" "Paylaş" 190624 Güzelliği tamamlandıktan sonra artık narin bir çocuk olmayan yakışıklı çocuk Milo
Alışveriş çılgınlığı 618'in ortasında geldi, Alman ve İtalyan sıcak satış davlumbazı önerilir
To Top