春天:对正确的学习路径感到困惑



在过去的几天里,我一直在自学Spring Boot,并创建了一个REST Web服务服务器和客户端,然后添加了基本身份验证并部署为独立和战争包。我通过将spring-boot-starter-webspring-boot-starter-testspring-boot-starterspring-boot-starter-securityspring-boot-starter-tomcatspring-webjackson-databind合并到我的gradle项目中,并通过各种网站复制hten修改来做到这一点。

在对众多网站以完全不同的方式(完全不同的注释,配置文件的一些使用)做事感到困惑之后,它起作用了,然后我使用拦截器/消息转换器,原始标头然后通过休息模板构建器对其进行了修改。

但是,我觉得我真的不知道它是如何或为什么工作的,即使我写了相当多的代码来让它以 4 种不同的方式工作,包括基本身份验证。它只是神奇地工作了,我不喜欢它:例如,如果我想添加更多不是基于"引导"的东西,我会怎么做,或者所有的注释都在做什么以及为什么需要它们,例如@SpringBootApplication@Configuration,或者为什么有些类是@Bean而另一些则不是)。

长话短说,spring是一个庞大的框架(列出软件包的网站自己占据了一个页面),我真的应该先学习spring核心/框架,那么在学习启动之前也许是Spring MVC或spring Web服务?

我可以找到许多关于教我各种软件包的资源,但没有一个能告诉我它们为什么工作或真正从哪里开始,特别是没有什么能告诉我软件包是如何相互链接的。这是相当压倒性的。

我预计这将因没有建设性而被关闭,但它似乎是在春季获得答案的最佳场所。

春天的短暂历史

让我们从一点历史课开始...这一年是 2002 年,大多数 Java 开发人员一直在 J2EE 领域工作,他们中的许多人并不满意。其中一位是 Rod Johnson,他写了一本名为 Expert One-on-One J2EE Design and Development 的书,它探讨了如何在没有 EJB 的情况下以更好的方式开发企业应用程序。本书的代码成为Spring框架的基础。

弹簧配置

让我们看一个简单的Java类。

@Component("hello")
public class HelloWorld {
private String name = "World!";
public void setName(String name) {
this.name=name;
}
public void sayHello() {
System.out.println("Hello, " + name);
}
}

弹簧配置 - 属性文件

一开始,唯一的配置选项是使用属性文件。让我们将此文件命名为application-context.properties。要创建上述 java 类的实例并设置名称,需要在application-context.properties中提供以下内容。

hello.(class)=biz.deinum.samples.configurations.HelloWorld
hello.name=Marten!

(class)是一个特殊的属性(还有更多类似的(scope)(abstract)查看javadoc以获取更多选项。这将指示需要加载哪个类。要使用属性文件,必须创建一个PropertiesBeanDefinitionReader传递该BeanFactory。(如果您需要像AOP这样的花哨功能,则可以将其传递给ApplicationContext)

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:application-context.properties");
HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();

但是,基于属性的配置有点限制,XML与世界一致。因此,进入XML配置的第一步诞生了。

Spring 配置 - XML 文件(第 1 部分)

要使用 XML 表示相同的配置,需要以下内容。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="biz.deinum.samples.configurations.HelloWorld">
<property name="name" value="Marten!" />
</bean>
</beans>

加载时,这将创建与属性文件具有相同设置的HelloWorld实例。加载它需要一个XmlBeanDefinitionReader.

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:/applicationContext-basic.xml");
HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();

Spring 配置 - XML 文件 (部分 2)

XML 非常冗长,但可读性强。但是配置AOP(例如事务),MVC等东西是相当费力的。(或者像安全性这样的东西,请参阅没有命名空间的 Spring Security 的前身)。因此,新的和改进的XML具有命名空间的概念,允许诸如<tx:annotation-driven /><aop:config />之类的东西。

弹簧配置 - 注释驱动

下一步是引入Java5,它允许注释。由于整个Java社区都要求基于注释的配置,因此添加了此配置。因此引入了@Component@Autowired等。

@Component添加到HelloWorld类并使用命名空间启用组件扫描可减少必须写入的 XML 量。

假设@Component("hello")位于HelloWorld类上,则需要以下 XML。

<?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">
<context:component-scan base-package="biz.deinum.samples.configurations" />
</beans>

要加载此配置,只需更改要加载的文件的位置。

Spring 配置 - Java 配置

然后突然之间,对XML的热爱结束了,人们想要使用他们知道的语言,这种语言就是Java。因此,基于Java的配置诞生了。

@Configuration
public class HelloWorldConfiguration {
@Bean
public HelloWorld hello() {
HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Marten!");
return helloWorld;
}
}

@Bean注释表明此方法生成一个 bean,并在由 Spring 实际加载之前使用 ASM 进行处理。但是,Java Config 处理非常复杂,并且仅适用于ApplicationContext。可以将@Configuration类添加到 xml 文件并加载该文件以对其进行处理,也可以使用专用AnnotationConfigApplicationContext加载(或检测)它。

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
context.getBean("hello", HelloWorld.class).sayHello();

在XML中,我们有命名空间,使配置更容易。在Java Config中,我们有各种@Enable*注释,如@EnableTransactionManagement,它与XML中的<tx:annotation-driven />相同。

想法/建议

使用哪个配置选项,如果您是新手,我建议从基于 Java 的配置开始,尽管 XML 可能更容易理解(恕我直言)。所有配置选项今天仍然有效,如果需要,您甚至可以混合搭配它们。

对于Spring来说,这并不重要,对Spring来说重要的是BeanDefinition哪个源用于构造它们(属性,xml或java配置)并不重要。

弹簧启动

到目前为止,唯一涵盖的是春天本身。没有触及其他项目(尽管已经提到)。但正如您可以想象的那样,随着时间的推移,随着配置和应用程序复杂性的增长,我们希望更多的约定而不是配置。Spring Boot看到曙光的原因之一。

@SpringBootApplication标记类会使该类成为@Configuration,将启用组件扫描(从注释类所在的同一包开始)并启用自动配置。

@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(HelloApplication.class, args);
BeanFactoryHelper.sayHello(context);
BeanFactoryHelper.statistics(context);
}
@Bean
public HelloWorld hello() {
HelloWorld hello = new HelloWorld();
hello.setName("Marten!");
return hello;
}
}

此类将启动应用程序,打个招呼,打印一些有关上下文的信息并结束。无需自己创建应用程序上下文或工厂。

为什么@Bean方法很好,HelloWorld类在一个包中,没有被 Spring Boot 的默认组件扫描所涵盖,因此我们需要声明 bean。我们可以在HelloApplication类中执行此操作,因为这也是一个@Configuration(因为它是@SpringBootApplication上的元注释)。

现在,如果您将@SpringBootApplication替换为@SpringBootApplication(scanBasePackageClasses = HelloWorld.class)则可以删除@Bean注释,因为现在可以通过组件扫描检测到HelloWorld(由@SpringBootApplication上的@ComponentScan元注释启用)。

可以在此处找到此答案的代码。

Spring框架 它是关于依赖注入的,它用于 REST Web 服务,但这并不意味着你不能在任何基本应用程序中使用 Spring。

长话短说,spring是一个庞大的框架(列出软件包的网站自己占据了一个页面),我真的应该先学习spring核心/框架,那么在学习启动之前也许是Spring MVC或spring Web服务?

你应该了解 Spring 的一般工作原理以及实例化是如何工作的。基本上,它会在您的项目中进行搜索,并实例化每个用@Component(@Service@RestController@Controller...等等)。当您@Autowire时,将向变量传递引用。

在对众多网站以完全不同的方式(完全不同的注释,配置文件的一些使用)做事感到困惑之后,它起作用了,然后我使用拦截器/消息转换器,原始标头然后通过休息模板构建器对其进行了修改。

您可以在互联网上找到的大多数超过 1-2 年的示例可能已经过时(但并非总是如此)。当您搜索某些内容时,请记住这一点。这是为什么有这么多实现的主要原因。

可以找到许多关于教我各种软件包的资源,但没有一个能告诉我它们为什么工作或真正从哪里开始,特别是没有什么能告诉我软件包是如何相互链接的。这是相当压倒性的。

这是压倒性的。这是一个具有大适用性的大框架。了解事物如何运作的最佳场所是:https://spring.io/docs/reference

最新更新