2011-01-14 14 views
5

Utilizziamo Spring A (3.0.5) AOP con annotazioni in stile @AspectJ e <aop:aspectj-autoproxy/> . Lo usiamo per transazioni, auditing, profiling, ecc. Funziona benissimo eccetto il fatto che il tempo di avvio dell'applicazione è in continua crescita man mano che viene aggiunto più codice.Spring AOP tempo di avvio lento

Ho effettuato alcuni profili e ho scoperto che la maggior parte del tempo viene spesa durante l'inizializzazione del contenitore Spring, in particolare org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory) - circa 35 secondi. org.springframework.aop.support.AopUtils.canApply(Pointcut, Class, boolean) - dura circa 15 sec.

Il mio obiettivo è che l'applicazione inizi tra 5 e 10 secondi e non ~ 45 secondi come ora, quindi qualsiasi suggerimento sarebbe molto apprezzato.

+0

Jumping a concludere che la primavera AOP provoca prestazioni di avvio è la conclusione affrettata. (Considerando la tessitura avviene in fase di esecuzione). Hai controllato le statistiche di JVM usando Jconsole o visualVm. Disponi di un metodo init personalizzato per alcuni dei tuoi bean. Hai provato a utilizzare l'inizializzazione pigra. (dalla proprietà lazy-init in bean)? –

+0

Questi sono i passi che seguirò. 1- Controlla le statistiche JVM durante il caricamento normale. 2. Rendere le proprietà di lazy-init dei bean come predefinite e quindi controllare di nuovo la stat jvm (uso della memoria e altri). 3- Se ancora non ci sono miglioramenti notevoli, allora spegnerò l'autoproduzione degli aspetti. Come ho detto, se dovessi piazzare una scommessa, sarò pronto a scommettere che la sua tessitura non AOP influisce sul tempo di caricamento. –

+0

Sono abbastanza sicuro che sia la tessitura da quando ho passato un sacco di tempo a profilare con Yourkit, prendendo solo discariche durante l'avvio e posizionando alcuni punti di interruzione e tutti i punti per la tessitura AOP. Ma io sono curioso quando dici che l'aspetto di chiusura è autoproxying qual è l'alternativa che suggerisci? Grazie, Yuval –

risposta

1

Ho avuto lo stesso problema, risulta che il proxy automatico di Spring AOP impiega molto tempo all'avvio durante il caricamento delle classi con bcel (senza cache, quindi caricando più e più volte le stesse classi come java.lang.Object ...) quando si cerca di capire quali consigli si applicano. Può essere un po 'migliorato scrivendo più tagli Punto a grana fine (usa dentro, @within per esempio) ma ho trovato una soluzione che ha funzionato meglio se tutti i tuoi punti di riferimento sono stati scritti con @annotation.

1) Disattivare il proxy automatico con: spring.aop.auto = false

2) sottoclasse personalizzata di AnnotationAwareAspectJAutoProxyCreator per filtrare i fagioli da decorare secondo i vostri propri criteri, ad esempio, questo si basa su pacchetto e annotazioni:

@Override 
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { 
    if (beanClass != null && isInPackages(beansPackages, beanClass.getName()) && hasAspectAnnotation(beanClass)) { 
    return super.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); 
    } else { 
    return DO_NOT_PROXY; 
    } 
} 

Nel mio caso il tempo di avvio verso il basso da 60 anni a 15s.

spero che aiuterà qualcuno e gli orsi polari

1

Non sono sicuro che si applica al tuo situtation, ma Spring performance can be improved by empolying a CachingBeanFactory.

Questo di solito si applica quando si collegano i bean, ma a seconda di come vengono applicati e cablati gli aspetti, si potrebbero apportare miglioramenti.

+0

Grazie, controllerò. –

+0

Ho provato questo metodo, non ha aiutato –

2

Apparentemente si tratta di un problema noto se si dispone di molti bean non singleton. Sembra esserci una soluzione per Spring 3.1: https://jira.springsource.org/browse/SPR-7328

+0

Grazie per il collegamento, questo probabilmente non è il caso, la maggior parte dei nostri fagioli sono singleton, ma questo è probabilmente connesso. –

+0

Sfortunatamente l'uso della cache AopUitls non ha aiutato né –

1

Hai una dipendenza circolare? Questo è ciò che sta uccidendo la mia app attuale.

So che non è davvero una soluzione, ma vorrei rompere il contesto per eseguire diversi servizi in diversi vms, in stile SOA. Ciò dovrebbe consentire a tutte le tue app di avere un tempo di avvio ridotto e dovrebbe anche darti una certa flessibilità per modificare l'implementazione di questi servizi più facilmente, una piccola quantità di codice da testare, ecc.

Non l'ho fatto in una delle mie app e ora di avvio è a circa 3/4 minuti, il che è pazzesco (abbiamo un paio di migliaia di fagioli). Questo problema non scompare, peggiorerà solo, ma se tenti di fare qualcosa a riguardo troppo tardi, l'app sarà troppo grande e troppo difficile da rompere.

Un'altra cosa che vorrei esaminare è l'ibernazione, la creazione della factory di sessione può essere piuttosto lenta.

+0

Grazie per i suggerimenti, come fai a sapere che avere una dipendenza circolare è ciò che sta uccidendo l'app? –

+0

Che IDE usi? ad esempio Intellij IDEA ha un'analisi delle dipendenze circolare sotto le opzioni del menu Analizza. –

5

Da quello che hai postato sembra che tu usi Load Time Weaving che incorre in una penalità di avvio perché il sistema deve tessere tutte le classi mentre vengono caricate. Se la tua preoccupazione principale è il tempo di avvio, ti suggerirei di passare alla compilazione del tempo di tessitura. Puoi trovare le istruzioni su come farlo nella documentazione di primavera (Capitolo 6, Sezione 8) o nel sito AspectJ (http://www.eclipse.org/aspectj/docs.php)

Passare a compilare tempo tessitura con il compilatore AspectJ è relativamente stragiht avanti:

  1. Rimuovere il <aop:aspectj-autoproxy/> notazione dal file contesto.
  2. Aggiungi un aspettoJ compila il passaggio al file di build . Sul sito AspectJ dovresti essere in grado di trovare un plugin per le formiche, codehaus ha un plug-in maven. Qui sono esempi di come entrambi.

Per Maven:

<plugin> 
    <groupId>org.codehaus.mojo</groupId> 
    <artifactId>aspectj-maven-plugin</artifactId> 
    <version>1.3</version> 
    <configuration> 
    <verbose>true</verbose> 
     <source>1.6</source> 
     <target>1.6</target> 
     <complianceLevel>1.6</complianceLevel> 
     <showWeaveInfo>true</showWeaveInfo> 
     <aspectLibraries> 
     <aspectLibrary> 
           <groupId>org.springframework</groupId> 
           <artifactId>spring-aspects</artifactId> 
          </aspectLibrary> 
         </aspectLibraries> 
        </configuration> 
        <executions> 
         <execution> 
          <goals> 
           <goal>compile</goal> 
          </goals> 
         </execution> 
        </executions> 
       </plugin> 

Per Ant

<taskdef 
      resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"> 
      <classpath> 
       <pathelement location="${lib.dir}/AspectJ_1.6.8/aspectjtools.jar"/> 
      </classpath> 
     </taskdef> 

    <iajc aspectPath="${file.reference.spring-aspects.jar}; ${build.classes.dir}/path/to/custom/aspects" 
       classpath="${lib.dir}/AspectJ_1.6.8/aspectjrt.jar; ${javac.classpath}" 
       inpath="${build.classes.dir}" 
       destDir="${build.classes.dir}" 
       showWeaveInfo="true" /> 
+0

Grazie per il suggerimento, ma passare alla compilazione del tempo di compilazione non è un'opzione, le persone con cui lavoro sono fortemente contrarie alle fasi di post-compilazione. –

+1

@Yuval: puoi almeno provarlo, per confermare che la tessitura del tempo di caricamento sta causando il ritardo? –

+0

@Bruno: ho fatto un primo tentativo e non ha funzionato correttamente, ma ci lavorerò ancora un po 'quando avrò più tempo e rapporto, grazie. –

0

Ho avuto lo stesso problema, prima che cambi jdk1.7 tornare a jdk1.6. Con jdk1.7, la mia app si blocca su "Inizializzazione di Spring root WebApplicationContext" per oltre 30 secondi. Dopo il cambio, avvio in 10 secondi.