Maison >Java >javaDidacticiel >Quel est le principe sous-jacent de SpringBoot ?
Dans le développement quotidien, il vous suffit d'introduire les dépendances suivantes pour développer un servlet d'accès.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Alors, comment ça se passe ? Découvrons-le aujourd'hui
Tout d'abord, créez un nouveau projet maven rick-spring-boot, et créez deux sous-projets, spring-boot et user. Le projet spring-boot consiste à simuler l'écriture manuscrite d'un simple springboot. . L'utilisateur est utilisé pour tester le spring-boot manuscrit.
projet utilisateur-test projet
Le projet utilisateur contient pom.xml, UserController et UserService
<dependencies> <dependency> <groupId>com.rick.spring.boot</groupId> <artifactId>spring-boot</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>rrree# 🎜 🎜# et la classe de démarrage RickApplication du projet utilisateur, et RickSpringApplication.run() est une classe de démarrage qui doit être écrite à la main et l'annotation @RickSpringBootApplication, qui doivent toutes deux être implémentées dans le projet spring-boot.
@RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user") public String getUser() { return userService.getUser(); } } @Service public class UserService { public String getUser() { return "rick"; } }Springboot projectRegardons d'abord ce que la méthode RickSpringApplication.run(RickApplication.class) doit faire : (1) Créer un conteneur Spring et enregistrez la classe entrante dans le conteneur Spring (2) Démarrez un service Web, tel que Tomcat, pour traiter la demande et distribuez la demande au Servlet pour traitement via DispatchServlet.
import com.rick.spring.boot.RickSpringApplication; import com.rick.spring.boot.RickSpringBootApplication; @RickSpringBootApplication public class RickApplication { public static void main(String[] args) { RickSpringApplication.run(RickApplication.class); } }RickApplication est modifié par l'annotation @RickSpringBootApplication. À partir du code suivant, nous pouvons voir que RickApplication est une classe de configuration. Après avoir été enregistrée dans le conteneur Spring, Spring analysera cette classe.
public class RickSpringApplication { public static void run(Class clz) { AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.register(clz); context.refresh(); start(context); } public static void start(WebApplicationContext applicationContext) { System.out.println("start tomcat"); Tomcat tomcat = new Tomcat(); Server server = tomcat.getServer(); Service service = server.findService("Tomcat"); Connector connector = new Connector(); connector.setPort(8081); Engine engine = new StandardEngine(); engine.setDefaultHost("localhost"); Host host = new StandardHost(); host.setName("localhost"); String contextPath = ""; Context context = new StandardContext(); context.setPath(contextPath); context.addLifecycleListener(new Tomcat.FixContextListener()); host.addChild(context); engine.addChild(host); service.setContainer(engine); service.addConnector(connector); tomcat.addServlet(contextPath, "dispatcher", new DispatcherServlet(applicationContext)); context.addServletMappingDecoded("/*", "dispatcher"); try { tomcat.start(); } catch (LifecycleException e) { e.printStackTrace(); } } }Démarrer la méthode principale du projet utilisateur RickApplication, Access UserController#🎜 🎜 #
Maintenant, un simple projet spring-boot a été intégré.
Configuration automatique
Lors de l'utilisation de Springboot, si nous ne voulons pas utiliser Tomcat comme service de traitement des requêtes , mais jetty Ou d'autres services Web, il suffit généralement d'exclure les dépendances tomcat pertinentes, puis d'introduire les dépendances jetty. Il s'agit du mécanisme d'assemblage automatique de springboot. Voyons ensuite comment il est implémenté
Définissez une interface de serveur Web et deux classes d'implémentation (tomcat et jetty), et écrivez le code pour démarrer les services tomcat et jetty
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Configuration @ComponentScan public @interface RickSpringBootApplication { }
public interface WebServer { void start(); } public class JettyServer implements WebServer{ @Override public void start() { System.out.println("start jetty"); } }
Définissez l'interface AutoConfiguration pour identifier les classes qui doivent être automatiquement assemblées. Définissez une autre classe WebServerAutoConfiguration, qui est représentée comme une classe de configuration de Spring. Enfin, nous devons importer cette classe et laisser Spring l'analyser. Ensuite, Spring analysera la méthode d'annotation @Bean pour charger le Bean. Notez que les deux méthodes suivantes définissent également l'annotation @RickConditionalOnClass pour déterminer si le bean doit être analysé. Si les conditions sont remplies, le bean sera analysé. Autrement dit, si la classe stockée dans Tomcat ou le serveur est appliquée, le bean sera analysé. de la méthode correspondante sera analysée,
public class TomcatServer implements WebServer, ApplicationContextAware { private WebApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = (WebApplicationContext) applicationContext; } @Override public void start() { System.out.println("start tomcat"); ... tomcat.addServlet(contextPath, "dispatcher", new DispatcherServlet(applicationContext)); context.addServletMappingDecoded("/*", "dispatcher"); try { tomcat.start(); } catch (LifecycleException e) { e.printStackTrace(); } } }# 🎜🎜# Regardons l'annotation @RickConditionalOnClass : Lorsque spring analyse une méthode annotée avec @RickConditionalOnClass, spring sait qu'elle est modifiée par @Conditional, et exécutera la correspondance () méthode de RickOnClassConditional pendant l'analyse pour déterminer si les conditions de chargement du bean sont remplies. match() essaiera de charger le nom du chemin de classe transmis si le fichier jar correspondant est introduit dans l'application, il se chargera avec succès et retournera true. Sinon, il retournera false.
public interface AutoConfiguration { } @Configuration public class WebServerAutoConfiguration implements AutoConfiguration { @Bean @RickConditionalOnClass("org.apache.catalina.startup.Tomcat") public TomcatServer tomcatServer() { return new TomcatServer(); } @Bean @RickConditionalOnClass("org.eclipse.jetty.server.Server") public JettyServer jettyWebServer() { return new JettyServer(); } }Présentation de WebServerAutoConfiguration, le moyen le plus simple et le plus grossier est d'importer cette classe via @Import(WebServerAutoConfiguration.class). Mais il est impossible pour Spring Boot de faire cela. Il n'est certainement pas bon d'écrire des centaines de configurations automatiques dans le code. Spring utilise le mécanisme SPI pour créer les répertoires et fichiers suivants dans le répertoire des ressources le JDK ServiceLoader charge les classes dans les fichiers ci-dessus. Lors de l'importation de cette classe via l'annotation @Import(WebServerImportSelector.class), Spring exécutera selectImports() lors de l'analyse de la classe de configuration, important ainsi WebServerAutoConfiguration dans le conteneur Spring, et Spring analysera cette classe de configuration.
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Conditional(RickOnClassConditional.class) public @interface RickConditionalOnClass { String value(); } public class RickOnClassConditional implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map<String, Object> annotation = metadata.getAnnotationAttributes(RickConditionalOnClass.class.getName()); try { context.getClassLoader().loadClass((String) annotation.get("value")); } catch (ClassNotFoundException e) { return false; } return true; } }À ce stade, Springboot peut basculer entre les services Tomcat et Jetty uniquement en modifiant la dépendance Maven du projet utilisateur
public class WebServerImportSelector implements DeferredImportSelector { @Override public String[] selectImports(AnnotationMetadata metadata) { ServiceLoader<AutoConfiguration> load = ServiceLoader.load(AutoConfiguration.class); List<String> list = new ArrayList<>(); for (AutoConfiguration loader : load) { list.add(loader.getClass().getName()); } return list.toArray(new String[list.size()]); } }Redémarrer le projet utilisateur
#🎜🎜 #
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!