¿Qué hace el marco Spring? ¿Debo usarlo? ¿Por qué o por qué no?

237

Entonces, estoy comenzando un nuevo proyecto en Java, y estoy considerando usar Spring. ¿Por qué estoy considerando la primavera? ¡Porque mucha gente me dice que debería usar Spring! En serio, cada vez que intento que la gente explique qué es exactamente Spring o qué hace, nunca me pueden dar una respuesta directa. He revisado las introducciones en el sitio SpringSource, y son realmente complicadas o están realmente centradas en los tutoriales, y ninguna de ellas me da una buena idea de por qué debería usarla o cómo me facilitará la vida. A veces las personas rechazan el término "inyección de dependencia", lo que me confunde aún más, porque creo que tengo una comprensión diferente de lo que significa ese término.

De todos modos, aquí hay un poco sobre mi experiencia y mi aplicación:

He estado desarrollando en Java por un tiempo, haciendo desarrollo web back-end. Sí, hago un montón de pruebas unitarias. Para facilitar esto, normalmente hago (al menos) dos versiones de un método: una que usa variables de instancia y otra que solo usa variables que se pasan al método. El que usa variables de instancia llama al otro, suministrando las variables de instancia. Cuando llega el momento de la prueba unitaria, uso Mockito para simular los objetos y luego hago llamadas al método que no usa variables de instancia. Esto es lo que siempre he entendido que es la "inyección de dependencia".

Mi aplicación es bastante simple, desde una perspectiva CS. Pequeño proyecto, 1-2 desarrolladores para comenzar. Principalmente operaciones de tipo CRUD con un montón de búsqueda. Básicamente, un montón de servicios web RESTful, más un front-end web y, finalmente, algunos clientes móviles. Estoy pensando en hacer el front-end en HTML / CSS / JS / JQuery directo, por lo que no hay planes reales para usar JSP. Usando Hibernate como ORM y Jersey para implementar los servicios web.

Ya comencé a codificar, y estoy ansioso por obtener una demostración que pueda comparar y ver si alguien quiere invertir. Entonces, obviamente, el tiempo es esencial. Entiendo que Spring tiene una curva de aprendizaje bastante grande, además parece que necesita una gran cantidad de configuración XML, que normalmente trato de evitar como la peste. Pero si puede hacerme la vida más fácil y (especialmente) si puede hacer que el desarrollo y las pruebas sean más rápidas, estoy dispuesto a morder la bala y aprender Spring.

Así que por favor. Educarme ¿Debo usar Spring? ¿Por qué o por qué no?

sangre fría
fuente
10
Creo que realmente necesitas probarlo por un tiempo para ver si te gusta y si es adecuado para tu proyecto. Personalmente lo odio.
Richard
1
Si bien puedes usar XML o anotaciones; tenga en cuenta que Spring toma una convención sobre la mentalidad de configuración. No es necesariamente una lista de elementos que tiene que abordar.
Aaron McIver
14
Si bien es cierto que esta pregunta es bastante amplia, creo que debería permanecer abierta. Lo leí como "¿Qué beneficios ofrece Spring para un proyecto de tamaño mediano?", Y esa es una buena pregunta.
sleske
1
Recomiendo leer mi libro técnico favorito: Spring in Action, Third Edition de Craig Walls. Es una gran lectura y cambiará la forma en que programa.
Alfredaday
44
Teniendo en cuenta Enterprise Java, es más fácil responder lo que Spring no hace ...
m3th0dman

Respuestas:

108

¿Qué hace el marco Spring? ¿Debo usarlo? ¿Por qué o por qué no?

Spring es un marco que te ayuda a "conectar" diferentes componentes entre sí. Es más útil en los casos en que tiene muchos componentes y puede decidir combinarlos de diferentes maneras, o si desea facilitar el intercambio de un componente por otro dependiendo de las diferentes configuraciones o entornos.

Esto es lo que siempre he entendido que es la "inyección de dependencia".

Sugeriría una definición diferente:

"Diseñe sus objetos para que confíen en una fuerza externa que les proporcione lo que necesitan, con la expectativa de que estas dependencias siempre se inyecten antes de que alguien les pida que comiencen a hacer sus trabajos habituales".

Compare eso con: "Cada objeto es responsable de salir y encontrar todo y todos los que necesita cuando se inicia".

parece que necesita un montón de configuración XML

Bueno, la mayoría de las cosas XML (o basadas en anotaciones) dicen cosas de Spring como:

  • Cuando alguien pregunta por "HammerStore", quiero que crees una instancia example.HammerStorey la devuelvas. Caché la instancia para la próxima vez, ya que solo tiene que haber una tienda.
  • Cuando alguien pregunta por "SomeHammer", quiero que te pidas un "HammerStore" y devuelvas el resultado del makeHammer()método de la tienda . No , no almacenar en caché este resultado.
  • Cuando alguien solicita "SomeWrench", quiero que cree una instancia de example.WrenchImpl, Use la configuración gaugeAmounty colóquela en la setWrenchSize()propiedad de la instancia . No guarde en caché el resultado.
  • Cuando alguien pregunta por "LocalPlumber", quiero que crees una instancia de example.PlumberImpl. Ponga la cadena "Pedro" en su setName()método, ponga un "SomeHammer" en su setHammer()método y ponga un "SomeWrench" en su setWrench()método. Devuelva el resultado y guarde en caché el resultado para más adelante, ya que solo necesitamos un plomero.

De esta forma, Spring le permite conectar componentes, etiquetarlos, controlar sus ciclos de vida / almacenamiento en caché y alterar el comportamiento según la configuración.

Para facilitar [las pruebas], normalmente hago (al menos) dos versiones de un método: una que usa variables de instancia y otra que solo usa variables que se pasan al método.

Eso suena como una gran cantidad de gastos generales para no un gran beneficio para mí. En su lugar, haga que sus variables de instancia tengan protectedvisibilidad o paquete , y ubique las pruebas unitarias dentro del mismo com.mycompany.whateverpaquete. De esa manera, puede inspeccionar y cambiar las variables de instancia cuando lo desee durante la prueba.

Darien
fuente
65

Primero, ¿qué es la inyección de dependencia?

Sencillo. Tiene una clase, tiene un campo privado (establecido en nulo) y declara un establecedor público que proporciona el valor para ese campo. En otras palabras, la dependencia de la clase (el campo) está siendo inyectada por una clase externa (a través del configurador). Eso es. Nada mágico

En segundo lugar, Spring se puede usar sin XML (o muy poco)

Si se sumerge con Spring 3.0.5.GA o superior, puede usar el soporte de inyección de dependencia de JDK6 +. Esto significa que puede conectar dependencias utilizando las anotaciones @Componenty @Resource.

¿Por qué usar Spring en absoluto?

Obviamente, la inyección de dependencias promueve pruebas de unidad muy fáciles ya que todas sus clases tienen configuradores para las dependencias importantes y se pueden burlar fácilmente usando su marco de burla favorito para proporcionar el comportamiento requerido.

Aparte de eso, Spring también proporciona muchas plantillas que actúan como clases base para hacer que el uso de las tecnologías estándar JEE sea muy fácil de usar. Por ejemplo, JdbcTemplate funciona bien con JDBC, JpaTemplate hace cosas buenas con JPA, JmsTemplate hace que JMS sea bastante sencillo. El RestTemplate es simplemente impresionante en su simplicidad. Por ejemplo:

RestTemplate restTemplate = new RestTemplate();
MyJaxbObject o = restTemplate.getForObject("https://secure.example.org/results/{param1}?param2={param2}",MyJaxbObject.class,"1","2");

y tu estas listo. Los parámetros se inyectan y solo necesita proporcionar anotaciones JAXB para MyJaxbObject. Eso no debería llevar tiempo si los ha generado automáticamente desde un XSD utilizando el complemento Maven JAXB. Tenga en cuenta que no hubo casting allí, ni hubo necesidad de declarar un mariscal. Todo está hecho por ti.

Podría comentar para siempre sobre las maravillas de Spring, pero tal vez lo mejor que puede hacer es probar un simple aumento de código donde intente conectar un servicio web RESTful para bombear datos de un DAO inyectado que admite transacciones.

Gary Rowe
fuente
44
Sí, RestTemplate es bastante impresionante. Tengo como 100 líneas de código que puedo tirar y reemplazar con 2-3 líneas.
Kevin
11
Para nitpick: Dependency Injection también incluye el enfoque basado en constructor. No necesariamente necesita tener setters.
Darien
28

En primer lugar, su comprensión de la inyección de dependencia no es fundamentalmente incorrecta, sino bastante diferente de lo que la mayoría de las personas quieren decir cuando usan el término. Lo que describe es una forma bastante extraña y poco convencional de lograr la capacidad de prueba. Te aconsejaría que te alejes de él, ya que otros desarrolladores estarán bastante desconcertados por ese tipo de código.

La inyección de dependencia como se entiende generalmente (e implementa Spring) significa que las dependencias que tiene una clase (por ejemplo, un origen de datos JDBC) no son recuperadas por la clase en sí, sino que un contenedor las "inyecta" cuando se crea la instancia. Por lo tanto, no tiene dos versiones de cada método que utiliza el origen de datos; en su lugar, tiene una configuración de inyección de dependencia donde se inyecta el origen de datos "real" y una donde se inyecta un simulacro. O, si la inyección se realiza a través del constructor o un getter, el código de prueba puede hacer la inyección explícitamente.

En segundo lugar, Spring no es solo una inyección de dependencia, aunque esa es su funcionalidad principal. También proporciona transacciones declarativas, programación de trabajos, autenticación y muchas otras funciones (incluido un marco web MVC completo) que puede necesitar. Hay otros marcos que proporcionan la misma funcionalidad, pero aparte de Spring, solo Java EE los tiene todos integrados.

Michael Borgwardt
fuente
OP entiende perfectamente DI
Basilevs
19

Para saber por qué desea usar Spring, puede leerlo en http://www.wrox.com/WileyCDA/Section/Why-Use-the-Spring-Framework-.id-130098.html

En resumen :

  • Las aplicaciones J2EE tienden a contener cantidades excesivas de código de "plomería". Muchas revisiones de código revelan repetidamente una alta proporción de código que no hace nada: código de búsqueda JNDI, Transferir objetos, bloques try / catch para adquirir y liberar recursos JDBC. . . . Escribir y mantener dicho código de plomería demuestra una gran pérdida de recursos que deberían centrarse en el dominio comercial de la aplicación.

  • Muchas aplicaciones J2EE usan un modelo de objetos distribuidos donde esto es inapropiado. Esta es una de las principales causas de código excesivo y duplicación de código. También es conceptualmente incorrecto en muchos casos; Las aplicaciones distribuidas internamente son más complejas que las aplicaciones de ubicación conjunta y, a menudo, son mucho menos eficaces. Por supuesto, si los requisitos de su negocio dictan una arquitectura distribuida, debe implementar una arquitectura distribuida y aceptar la compensación que incurre (y Spring ofrece características para ayudar en tales escenarios). Pero no deberías hacerlo sin una razón convincente.

  • El modelo de componente EJB es excesivamente complejo. EJB fue concebido como una forma de reducir la complejidad al implementar la lógica de negocios en aplicaciones J2EE; no ha tenido éxito en este objetivo en la práctica.

  • EJB está sobreutilizado. EJB fue diseñado esencialmente para aplicaciones transaccionales distribuidas internamente. Si bien casi todas las aplicaciones no triviales son transaccionales, la distribución no debe integrarse en el modelo de componente básico.

  • Muchos "patrones de diseño J2EE" no son, de hecho, patrones de diseño, sino soluciones para limitaciones tecnológicas. El uso excesivo de la distribución y el uso de API complejas, como EJB, han generado muchos patrones de diseño cuestionables; Es importante examinarlos críticamente y buscar enfoques más simples y productivos.

  • Las aplicaciones J2EE son difíciles de probar en la unidad. Las API J2EE, y especialmente, el modelo de componente EJB, se definieron antes de que despegara el movimiento ágil. Por lo tanto, su diseño no tiene en cuenta la facilidad de las pruebas unitarias. A través de las API y los contratos implícitos, es sorprendentemente difícil probar aplicaciones basadas en EJB y muchas otras API J2EE fuera de un servidor de aplicaciones. Sin embargo, las pruebas unitarias fuera de un servidor de aplicaciones son esenciales para lograr una alta cobertura de prueba y reproducir muchos escenarios de falla, como la pérdida de conectividad a una base de datos. También es vital para garantizar que las pruebas se puedan ejecutar rápidamente durante el proceso de desarrollo o mantenimiento, minimizando el tiempo improductivo en espera de la redistribución.

  • Ciertas tecnologías J2EE simplemente han fallado. El principal delincuente aquí son los beans de entidad, que han demostrado ser poco desastrosos para la productividad y en sus limitaciones en la orientación a objetos.

Rudy
fuente
13

Solíamos escribir aplicaciones y servicios web simples, eficientes y rápidos utilizando solo Java, Servlets y JSP, html y xml, API JDBC. Fue lo suficientemente bueno; JUnit fue una buena herramienta para probar. Descansamos fácilmente que nuestro código funcionó.

Hibernate se presentó para simplificar SQL y habilitar el mapeo verdadero de las tablas de la base de datos con objetos Java, permitiendo que las relaciones jerárquicas se reflejen en el Mapeo de Relaciones de Objetos o ORM como lo llamamos. Me encantó. Especialmente que no tuvimos que asignar el ResultSet de nuevo a un objeto Java o tipo de datos.

Struts apareció para agregar el patrón Model View Controller a nuestras aplicaciones web, fue bueno.

Los EJB eran una gran sobrecarga y el dolor y las anotaciones hacían que el código pareciera un rasguño de pollo y ahora Spring surgió sobre nosotros, personas inocentes. Simplemente me parece exagerado.

Por ejemplo, ahora empaquetamos nuestra url jdbc simple, user, pasamos primero a jdbc.properties, luego a las propiedades de hibernación y luego a Spring beans por tercera vez.

En comparación con todo eso, considere obtener una conexión donde la necesite es realmente tan simple como se muestra a continuación en Java puro, que es lo que realmente estamos haciendo después de pasar por todas esas cosas de aire caliente con Spring:

Connection connection = DriverManager.getConnection(url, user, pass);

Eso se explica por sí mismo que es una gran vuelta y vuelta y vuelta para hacer una cosa simple de manera rápida y fácil sin otros grandes beneficios realmente. Es como envolver toneladas y toneladas de papel de regalo alrededor de un pequeño regalo que es todo lo que realmente conservas de todos modos.

Otro ejemplo es una actualización por lotes. Con Spring es complicado involucrando bastantes clases, interfaces antes de que pueda usar JdbcTemplate para hacer una actualización por lotes. Con jdbc simple es simplemente:

Statement statement = connection.createStatement();
statement.addBatch(sqlquery);
statement.executeBatch();

No puede ser más simple o más rápido que eso.

No apoyo este marco. Lo siento. ¿Quién demonios quiere inyecciones cada vez que necesita algo?

Uma
fuente
66
ese código es simple, pero ¿dónde se define su manejo de translación y cómo lo prueba? Ambas cosas se simplifican en primavera. Además, su código Java está directamente vinculado a una conexión db, a menos que almacene las direcciones URL de conexión y las contraseñas externamente, esto también se simplifica en primavera.
NimChimpsky
+1 para esta respuesta, para abordar el comentario anterior, el hombre usa sus propios patrones de diseño livianos (GOF), singleton para la agrupación de conexiones, una clase de proxy que proporciona sql (cadena) y valores (matriz) al Objeto de base de datos (qué método , depende del método http), el dbobject maneja la agrupación de conexiones, transacciones, etc. ejecutando la consulta seguida de la liberación. Uso de un objeto en todos los módulos, nadie necesita un código de placa de caldera excesivo. punto extra con la configuración de pruebas unitarias en la clase proxy y dbobject.
user2727195
¡Echa un vistazo a Spring-Data-JPA! Anote un pojo en una entidad, implemente una interfaz y defina firmas de métodos con nombres razonables, como findHammerByWeight (), y spring implemente los métodos por usted, proporcionándole un depósito inyectable que puede usar en todos sus otros servicios comerciales o clases de controlador .
mancini0
13

¿Qué hace el marco Spring?

La primavera es como hoy no solo, lo que se conoce como un marco simple, es un ecosistema completo.

Temas cubiertos por el ecosistema de primavera:

  • Spring Framework (por ejemplo, inyección de dependencia, AOP ...)

  • Nube de primavera

  • Datos de primavera

  • Seguridad de primavera

  • Lote de primavera

  • Spring Social

Vea aquí para una cobertura completa del ecosistema. Es posible seleccionar proyectos, para que pueda usar Google Guice para DI y, por ejemplo, Spring Security para manejar cosas relacionadas con la seguridad. NO tiene que comprar en todo el ecosistema.

El propio Spring-framework cubre hoy principalmente

  • Inyección de dependencia

  • Programación orientada a aspectos, incluida la gestión de transacciones declarativas de Spring

  • Aplicación web Spring MVC y marco de servicio web RESTful

  • Soporte fundamental para JDBC, JPA, JMS

Fuente spring.io

En general, se podría decir que Spring es una colección de patrones y prácticas implementados en código, que podría ayudar a mejorar o acelerar el ciclo de desarrollo de su aplicación.

Por lo que es más conocido (el core-framework) es por sus capacidades en el campo de la inyección de dependencias . El propio resorte tiene, lo que se llama Inversión del contenedor de control o corto Contenedor IoC o incluso el contenedor más corto (para el cual "resorte" a veces se usa como sinónimo).

¿Qué es la inyección de dependencia?

La inyección de dependencia significa que su objeto recibe cada dependencia de otros objetos a través de un mecanismo externo.

Digamos que tiene un automóvil, la forma típica en que se implementa es:

public class Car {

    Engine e;

    public Car() { 
        e = new Engine(); 
    }

}

El objeto del automóvil depende de un motor. Dado que el motor se implementa como un miembro del automóvil, no se puede cambiar por, por ejemplo, un motor de prueba.

Ahora entra en juego la inyección de dependencia :

public class Car {

    Engine e;

    public Car(Engine e) { 
        this.e = e; 
    }

}

Después de eso, puedes cambiar de motor. Lo que ves arriba se llama inyección de constructor . Hay otros tipos como, por ejemplo, setter -injection o method -injection. ¿Cómo te ayuda Spring con esto? Spring le permite marcar los componentes que se inyectarán con la anotación @Autowiredy realiza el cableado del objeto inyectado automáticamente; es probable que el componente que desea inyectar tenga dependencias. Los inyectables, por así decirlo, se marcan mediante@Component

public class Car {

    Engine e;

    @Autowired
    public Car(Engine e) { 
        this.e = e; 
    }

}

Pero esa es solo una de las muchas características que Spring tiene para ofrecer.

¿Debo usar Spring? ¿Por qué o por qué no?

Dado que Spring no es muy intrusivo y ofrece muchas ayudas, debería considerar usar spring. Especialmente para nuevos proyectos, Spring Boot es muy atractivo. start.spring.io ofrece una interfaz fácil de usar de apuntar y hacer clic para generar una plantilla de proyecto para comenzar. Incluso es posible usar curlpara recuperar una plantilla:

curl start.spring.io

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

:: Spring Initializr ::  https://start.spring.io

This service generates quickstart projects that can be easily customized.
Possible customizations include a project's dependencies, Java version, and
build system or build structure. See below for further details.

The services uses a HAL based hypermedia format to expose a set of resources
to interact with. If you access this root resource requesting application/json
as media type the response will contain the following links:
+-----------------+-----------------------------------------+
| Rel             | Description                             |
+-----------------+-----------------------------------------+
| gradle-build    | Generate a Gradle build file            |
| gradle-project  | Generate a Gradle based project archive |
| maven-build     | Generate a Maven pom.xml                |
| maven-project * | Generate a Maven based project archive  |
+-----------------+-----------------------------------------+

...

Por otro lado, los marcos como spark o dropwizard también ofrecen un buen punto de partida para la creación rápida de aplicaciones web.

Thomas Junk
fuente
1
Respuesta muy informativa!
GOXR3PLUS
De acuerdo, muy buena respuesta. OP, simpatizo contigo. También he hecho que varias personas me muestren demostraciones de Spring donde "simplifican" el código al agregar un archivo XML y 2 capas de indirección solo para que puedan llamar al constructor en una clase :) Realmente solo necesitas sumergirte o ir a un muy buena presentación y eventualmente quedará claro dónde están los beneficios y los inconvenientes
Adam Hughes
4

Es un marco escrito en Java con muchas cosas incluidas para que su aplicación web sea funcional (por ejemplo, soporte para la internacionalización). También proporciona una buena forma de estructurar su aplicación en capas. Úselo, le ahorrará mucho tiempo a largo plazo.

Un buen libro para aprender sobre Spring es: Expert Spring MVC y Web Flow

Bernardo
fuente