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

时间:2017-01-16 17:45:52

标签: spring spring-boot

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

在众多网站以完全不同的方式处理事情(完全不同的注释,一些配置文件的使用)之后,它工作了,然后我使用拦截器/消息转换器,原始标头然后通过休息模板修改它助洗剂。

但是,我觉得我真的不知道它是如何工作的,为什么它有效呢,尽管我用4种不同的方式编写了一些代码来完成所有工作,包括基本身份验证。它只是神奇地工作,我不喜欢它:例如,如果我想添加更多不是“启动”的东西,我将如何做,或者所有注释都在做什么以及为什么需要它们,例如@SpringBootApplication@Configuration或为什么某些课程@Bean而其他课程没有。{/ p>

简而言之,spring是一个庞大的框架(列出软件包的网站单独占用一个页面),我应该先学习spring core / framework之前的其他东西,那么可能是spring MVC或spring web services在学习启动之前?

我可以找到许多资源来教我不同的软件包,但没有一个可以告诉我它们为什么工作或者从哪里开始,特别是没有什么能告诉我这些软件包是如何相互链接的。这是非常压倒性的。

我希望这会被关闭而不是建设性的,但它似乎是获得Spring答案的最佳位置。

2 个答案:

答案 0 :(得分:5)

Spring的历史非常短暂

让我们从一个历史课开始......这一年是2002年,大多数Java开发人员都在J2EE领域工作,其中很多人都不高兴。其中一个是Rod Johnson,他写了一本名为Expert One-on-One J2EE Design and Development的书,它是如何在没有EJB和更好的方式的情况下开发企业应用程序的。本书的代码成为Spring Framework的基础。

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);
    }
}

Spring配置 - 属性文件

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

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

(class)是一个特殊属性(更像是(scope)(abstract),请参阅javadoc了解更多选项。这表明需要加载哪个类要使用属性文件,必须创建一个BeanFactory传递ApplicationContext。(如果您需要像AOP这样的花哨功能,则可以将其传递给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 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>

然而,基于属性的配置有点限制,XML正在向全世界表示赞同。因此,出生的XML配置的第一步。

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

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

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();

<tx:annotation-driven />

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

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

Spring配置 - 注释驱动

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

HelloWorld添加到@Component("hello")类并使用命名空间来启用组件扫描可以减少必须编写的XML数量。

假设HelloWorld类上有<?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> ,则需要以下XML。

@Configuration
public class HelloWorldConfiguration {

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

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

Spring配置 - Java配置

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

@Bean

ApplicationContext注释表示此方法生成bean并在Spring实际加载之前使用ASM进行处理。但是,Java Config处理非常复杂,仅适用于@Configuration。您可以将AnnotationConfigApplicationContext类添加到xml文件中并加载它以使其处理或使用专门的AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class); context.getBean("hello", HelloWorld.class).sayHello(); 来加载(或检测)它。

@Enable*

在XML中,我们有用于简化配置的命名空间。在Java Config中,我们有@EnableTransactionManagement个注释,如<tx:annotation-driven />,与XML中的BeanDefinition相同。

思考/建议

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

对于Spring来说,无关紧要,对于Spring来说最重要的是@SpringBootApplication哪个源用于构造它们(属性,xml或java配置)并不重要。

Spring Boot

到目前为止,唯一涵盖的是Spring本身。没有其他项目被触及(虽然已经提到)。但随着时间的推移,随着配置和应用程序复杂性的增长,我们想要更多this。 Spring Boot看到光明的原因之一。

使用@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类和HelloApplication类都在Spring Boot的默认组件扫描未涵盖的包中,因此我们需要声明bean。我们可以在@Configuration类中执行此操作,因为它也是@SpringBootApplication(因为它是@SpringBootApplication上的元注释)。

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

可以找到此答案的代码convention over configuration

答案 1 :(得分:2)

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

  

简而言之,spring是一个庞大的框架(列出软件包的网站单独占用一个页面),我应该先学习spring core / framework之前的其他东西,那么可能是spring MVC或spring web services在学习启动之前?

您应该了解spring的工作原理以及实例化的工作原理。基本上它会在您的项目中进行搜索并实例化每个使用 //top of your class let locManger = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() //request user location locManager.startUpdatingLocation() //this is the code that sets the region based on the location let span = MKCoordinateSpanMake(0.5, 0.5) let location = CLLocationCoordinate2DMake((locManager.location?.coordinate.latitude)!, (locManager.location?.coordinate.longitude)!) let region = MKCoordinateRegionMake(location, span) yourMap.setRegion(region, animated: false) //stop location updating locManager.stopUpdatingLocation() } 注释的类(@Component@Service@RestController ......等等。当您@Controller时,会将引用传递给您的变量。

  

在众多网站以完全不同的方式处理事情(完全不同的注释,一些配置文件的使用)之后,它工作了,然后我使用拦截器/消息转换器,原始标头然后通过休息模板修改它助洗剂。

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

  

我可以找到许多资源来教我不同的软件包,但没有一个可以告诉我它们为什么工作或者从哪里开始,特别是没有什么能告诉我这些软件包是如何相互链接的。这是非常压倒性的。

这是压倒性的。它是一个具有广泛适用性的大框架。了解事情如何运作的最佳地点是:https://spring.io/docs/reference