je suis nouveau au printemps et j'ai lu ceci:
Fondamentalement, un haricot a des portées qui définissent leur existence sur l'application
Singleton: signifie une définition de bean unique pour une instance d'objet unique par conteneur Spring IOC.
Prototype: désigne une définition de bean unique pour un nombre quelconque d'instances d'objet.
Alors, quelle est la "instance d'objet".
Prototype scope = Un nouvel objet est créé chaque fois qu'il est injecté/recherché. Il utilisera new SomeClass()
à chaque fois.
Singleton scope = (Par défaut)} _ Le même objet est renvoyé chaque fois qu'il est injecté/recherché. Ici, il instanciera une instance de SomeClass
et le renverra à chaque fois.
Voir également:
Regardons simplement ceci dans le code.
Voici un haricot TennisCoach avec la valeur par défautsingleton
Scope
@Component
@Scope("singleton")
public class TennisCoach implements Coach {
public TennisCoach(){
}
@Autowired
public void setFortuneService(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
@Override
public String getDailyFortune() {
return "Tennis Coach says : "+fortuneService.getFortune();
}
}
Voici un haricot TennisCoach avec prototype scope
@Component
@Scope("prototype")
public class TennisCoach implements Coach {
public TennisCoach(){
System.out.println(">> TennisCoach: inside default constructor");
}
@Autowired
public void setFortuneService(FortuneService fortuneService) {
System.out.println(">> Tennis Coach: inside setFortuneService");
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
@Override
public String getDailyFortune() {
return "Tennis Coach says : "+fortuneService.getFortune();
}
}
Voici un cours principal:
public class AnnotationDemoApp {
public static void main(String[] args) {
// read spring config file
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// get the bean from the spring container
Coach theCoach = context.getBean("tennisCoach",Coach.class);
Coach alphaCoach = context.getBean("tennisCoach",Coach.class);
// call a method on the bean
System.out.println("Are the two beans same :" + (theCoach==alphaCoach));
System.out.println("theCoach : " + theCoach);
System.out.println("alphaCoach: "+ alphaCoach);
context.close()
}
}
Pour singleton scope, le résultat est le suivant:
Are the two beans same :true
theCoach : com.springdemo.TennisCoach@2a53142
alphaCoach: com.springdemo.TennisCoach@2a53142
Pour prototype scope, le résultat est le suivant:
Are the two beans same :false
theCoach : com.springdemo.TennisCoach@1b37288
alphaCoach: com.springdemo.TennisCoach@1a57272
J'espère que ça répond à ta question. :RÉ
Ajouter à ce qui précède..ne confondez-vous avec le singleton Java . Selon Java Spec, singleton signifie qu'une seule instance de ce bean sera créée par JVM . être créé par contexte d'application . Ainsi, si votre application comporte plus d'un contexte, vous pouvez toujours avoir plus d'une instance pour ce bean.
Ce sont deux modèles de conception créatifs.
Singleton créera une nouvelle instance lors du premier appel et la renverra lors des appels suivants.
Le prototype renverra une nouvelle instance à chaque fois.
Singleton Scope: Avec la portée Singleton, une et une seule instance d'un bean est créée avec la définition de bean fournie. Pour les demandes suivantes relatives au même bean, le conteneur Spring renvoie la même instance.
De la documentation de printemps:
.. lorsque vous définissez une définition de haricot et que celle-ci est définie comme un singleton, le conteneur Spring IoC crée exactement une instance de l'objet défini par cette définition de haricot. Cette instance unique est stockée dans un fichier cache de tels singleton beans, et toutes les demandes ultérieures et les références pour ce bean nommé renvoient l'objet mis en cache ...
Exemple: Disons que nous avons défini un bean accountDao
comme ci-dessous:
<bean id="accountDao" class="" />
Et deux autres haricots, qui utilisent ce haricot accountDao
<bean id="someBean" ref="accountDao" />
<bean id="anotherBean" ref="accountDao" />
Spring créera initialement accountDao
bean et le mettra en cache. Et puis, pour someBean
et anotherBean
, il fournira la même instance de accountDao
.
Remarque: Si aucune étendue n'est spécifiée avec la définition du bean, Singleton est l'étendue par défaut.
Portée du prototype: Pour la portée du prototype, pour chaque demande de bean, une nouvelle instance du bean sera créée et renvoyée. Ceci est similaire à l'appel de l'opérateurnewen Java pour une classe.
Exemple: Disons que nous avons défini un bean accountDao
comme ci-dessous:
<bean id="accountDao" class="" scope="prototype"/>
Et deux autres haricots, qui utilisent ce haricot accountDao
<bean id="someBean" ref="accountDao" />
<bean id="anotherBean" ref="accountDao" />
Pour SpringBean et anotherBean, Spring renverra deux instances distinctes de l'objet accountDao.
Une différence importante est que, pour la portée du prototype, Spring ne gère pas le cycle de vie complet du bean, le nettoyage doit être effectué à l'aide du code client.
De la documentation de printemps:
Spring ne gère pas le cycle de vie complet d'un prototype de bean: le fichier conteneur instancie, configure et assemble autrement un objet prototype, et le remet au client, sans autre enregistrement de cette instance de prototype. Ainsi, bien que le cycle de vie d'initialisation Les méthodes de rappel sont appelées sur tous les objets, quelle que soit leur étendue, dans le fichier Dans le cas de prototypes, les rappels de cycle de vie de destruction configurés ne sont pas appelé. Le code client doit nettoyer les objets à portée prototype et libérez des ressources coûteuses que le ou les prototypes de haricots contiennent.
Je souhaite ajouter quelques informations supplémentaires susceptibles de nous aider à déterminer le sens du terme "instance d'objet" dans les phrases mentionnées. Ce paragraphe de Spring Doc tente de définir "instance d'objet":
Lorsque vous créez une définition de bean, vous créez une recette pour créer des instances actual de la classe définie par cette définition de bean . L'idée qu'une définition de haricot est une recette est importante, car cela signifie que, comme avec une classe, vous pouvez créer plusieurs instances d'objet à partir d'une même recette.
Par conséquent, comme mentionné dans la section ci-dessus, chaque définition de bean peut être considérée comme une classe (en termes d'objet). Selon les données que vous y avez définies (telles que scope, ...), cette classe (ou définition de bean) peut n'avoir qu'une seule instance d'objet (la portée singleton par une seule instance partagée) ou n'importe quel nombre d'instances d'objet portée du prototype en créant une nouvelle instance de bean chaque fois qu'une demande pour ce bean spécifique est faite).
Remarque: Un bean de portée quelconque sera créé s'il est référencé par d'autres beans et appelé à l'aide du contexte d'application.
Exemple de code pour vérifier cela.
public class PrototypeClass {
PrototypeClass()
{
System.out.println("prototype class is created"+this.toString());
}
}
Cela imprimera le texte pertinent lorsque le constructeur est appelé.
pour le code ci-dessous
for(int i=0;i<10;i++) {
PrototypeClass pct= (PrototypeClass) context.getBean("protoClass");
}
la classe prototype est createdSpring.PrototypeClass@29774679 prototype la classe est createdSpring.PrototypeClass@3ffc5af1, la classe prototype est createdSpring.PrototypeClass@5e5792a0 La classe de prototype est createdSpring.PrototypeClass@26653222 La classe de prototype est createdSpring.PrototypeClass@3532ec19 La classe de prototype est createdSpring.PrototypeClass@68c4039c La classe de prototype est createdSpring.PrototypeClass@ae45eb6 La classe de prototype est createdSpring.PrototypeClass@59f99ea La classe de prototype est createdSpring.PrototypeClass@27efef64 La classe de prototype est createdSpring.PrototypeClass@6f7fd0e6 La classe de prototype est createdSpring.PrototypeClass@47c62251
La définition de haricot est
<bean id="protoClass" class="Spring.PrototypeClass" scope="prototype</bean>
Maintenant, j'ai changé la portée de la définition du bean en singleton. Le constructeur n'est appelé qu'une fois lors de l'initialisation du contexte. Ensuite, j'ai supprimé l'attribut scope et observé le même comportement que singleton.
Singleton est la même instance dans toute l'application
Le prototype est une nouvelle instance pour chaque nouvelle requête de getBean
Portée du prototype: Un nouvel objet est créé chaque fois qu'il est injecté.
Singleton scope: Le même objet est renvoyé à chaque injection.
La portée du prototype est utilisée pour tous les beans qui ont un état, alors que la portée du singleton devrait être utilisée pour les beans sans état… .. Laissez-moi vous expliquer avec mon exemple. Copiez-le et lancez-le par vous-même pour bien comprendre. Considérons un coach d'interface.
public interface Coach {
public String getDailyWorkout();
public String getDailyFortune();
}
Nous avons une autre classe appelée TrackCoach qui implémente Coach.
public class TrackCoach implements Coach {
private FortuneService fortuneService;
public TrackCoach(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Run a hard 5k";
}
@Override
public String getDailyFortune() {
return "Just Do it: " + fortuneService.getFortune();
}
}
Il existe maintenant une interface FortuneService.
public interface FortuneService {
public String getFortune();
}
Il est implémenté par notre classe HappyFortuneService.
public class HappyFortuneService implements FortuneService {
@Override
public String getFortune() {
return "Today is your lucky day!";
}
}
Câblons les deux classes et injectons un objet bean d'une classe dans une autre à l'aide de XML. Faisons l'injection de dépendance. Notez que nous pouvons aussi le faire en utilisant une annotation Java.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Define your beans here -->
<!-- define the dependency -->
<bean id = "myFortuneService"
class = "com.luv2code.springdemo.HappyFortuneService">
</bean>
<bean id = "myCoach"
class = "com.luv2code.springdemo.TrackCoach"
scope = "singleton">
<!-- set up construction injection -->
<constructor-arg ref = "myFortuneService" />
</bean>
</beans>
Notez que scope = singleton
.
Définissons maintenant notre BeanScopeDemoApp, qui a notre méthode principale.
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanScopeDemoApp {
public static void main(String[] args) {
// load the spring configuration file
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("beanScope-applicationContext.xml");
// retrieve bean from spring container
Coach theCoach = context.getBean("myCoach", Coach.class);
Coach alphaCoach = context.getBean("myCoach", Coach.class);
// check if they are the same
boolean result = (theCoach == alphaCoach);
// print out the results
System.out.println("\nPointing to the same object: " + result);
System.out.println("\nMemory location for theCoach: " + theCoach);
System.out.println("\nMemory location for alphaCoach: " + alphaCoach +"\n");
// close the context
context.close();
}
}
Une fois que vous exécutez le code ci-dessus, vous verrez les résultats suivants:
Pointing to the same object: true
Memory location for theCoach: com.luv2code.springdemo.TrackCoach@16515bb7
Memory location for alphaCoach: com.luv2code.springdemo.TrackCoach@16515bb7
Il pointe le même objet et occupe le même emplacement mémoire après l'avoir appelé deux fois. Maintenant, changeons le scope = prototype
dans notre fichier XML, sauvegardons-le et exécutez à nouveau BeanScopeDemoApp.
Vous verrez les résultats suivants:
Pointing to the same object: false
Memory location for theCoach: com.luv2code.springdemo.TrackCoach@6d4d203d
Memory location for alphaCoach: com.luv2code.springdemo.TrackCoach@627fbcda
Cela pointe l'objet différent et occupe les différents emplacements de mémoire après l'avoir appelé deux fois ... Ceci serait une illustration graphique de ce que je viens de dire.