2010-06-30 15 views
388

Estoy un poco confundido sobre cómo funciona el inversion of control (IoC) en Spring.¿Cómo funciona el autoenvío en Spring?

Digamos que tengo una clase de servicio llamada UserServiceImpl que implementa la interfaz UserService.

¿Cómo sería esto @Autowired?

Y en mi acción Controllers, ¿cómo podría yo instantiate un instance de este servicio?

¿Haría lo siguiente?

UserService userService = new UserServiceImpl(); 
+0

duplicado posible de [Entendiendo uso Primavera @Autowired] (https: // stackoverflow.com/questions/19414734/understanding-spring-autowired-usage) – tkruse

Respuesta

570

En primer lugar, y más importante - todos los granos de la primavera son administrados - que "en vivo" dentro de un recipiente, llamado "contexto de aplicación".

En segundo lugar, cada aplicación tiene un punto de entrada a ese contexto. Las aplicaciones web tienen un Servlet, JSF usa un el-resolver, etc. Además, hay un lugar donde el contexto de la aplicación se inicializa y todos los beans se autoconectan. En aplicaciones web, esto puede ser un oyente de inicio.

El autoenrutamiento ocurre colocando una instancia de un frijol en el campo deseado en una instancia de otro frijol. Ambas clases deben ser beans, es decir, deben definirse para vivir en el contexto de la aplicación.

¿Qué es "vivir" en el contexto de la aplicación? Esto significa que el contexto instancia los objetos, no usted. Es decir. - Nunca hace new UserServiceImpl() - el contenedor encuentra cada punto de inyección y establece una instancia allí.

En sus controladores, que acaba de tener lo siguiente:

@Controller // Defines that this class is a spring bean 
@RequestMapping("/users") 
public class SomeController { 

    // Tells the application context to inject an instance of UserService here 
    @Autowired 
    private UserService userService; 

    @RequestMapping("/login") 
    public void login(@RequestParam("username") String username, 
      @RequestParam("password") String password) { 

     // The UserServiceImpl is already injected and you can use it 
     userService.login(username, password); 

    } 
} 

algunas notas:

  • En su applicationContext.xml que debe permitir a la <context:component-scan> por lo que las clases se analizan en busca de la @Controller, @Service, anotaciones, etc.
  • El punto de entrada para una aplicación Spring-MVC es el DispatcherServlet, pero está oculto y, por lo tanto, la interacción directa y el arranque del contexto de la aplicación ocurren detrás de la escena.
  • UserServiceImpl también se debe definir como bean, ya sea usando <bean id=".." class=".."> o usando la anotación @Service. Como será el único implementador de UserService, se inyectará.
  • Además de la anotación @Autowired, Spring puede usar el autoconexión configurable por XML. En ese caso, todos los campos que tienen un nombre o tipo que coincide con un bean existente obtienen automáticamente un bean inyectado. De hecho, esa fue la idea inicial del autoenvío: tener campos inyectados con dependencias sin ninguna configuración. Otras anotaciones como @Inject, @Resource también se pueden utilizar.
+0

su último punto, por lo que en la implementación de la interfaz, UserServiceImpl, anoto con @Service correcto? Una gran respuesta, REALMENTE aclaró las cosas para mí. – Blankman

+0

es UserService userService la interfaz? – Blankman

+6

sí, UserServiceImpl está anotado con Service, y UserService es la interfaz – Bozho

57

Depende de si fue la ruta de las anotaciones o la ruta de definición XML del bean.

Supongamos que tenía los beans definidos en su applicationContext.xml:

<beans ...> 

    <bean id="userService" class="com.foo.UserServiceImpl"/> 

    <bean id="fooController" class="com.foo.FooController"/> 

</beans> 

El autowiring sucede cuando se inicia la aplicación. Así, en fooController, que por argumentos bien quiere utilizar la clase UserServiceImpl, que le anotaciones de la siguiente manera:

public class FooController { 

    // You could also annotate the setUserService method instead of this 
    @Autowired 
    private UserService userService; 

    // rest of class goes here 
} 

Cuando se ve @Autowired, Primavera buscará una clase que coincide con la propiedad en el applicationContext, e inyectarlo automáticamente. Si tiene más de 1 bean UserService, tendrá que calificar cuál debería usar.

Si hace lo siguiente:

UserService service = new UserServiceImpl(); 

No va a recoger el @Autowired a menos que establezca por sí mismo.

+1

Entonces, ¿cuál es el uso de la definición de 'bean id' en' applicationContext.xml'. Tendremos que definir la variable 'userService' con el tipo' UserService'. Entonces, ¿por qué hacer la entrada en el archivo 'xml'. – viper

16

@Autowired es una anotación presentada en Spring 2.5, y se usa solo para inyección. Por ejemplo:

class A { 

    private int id; 

    // With setter and getter method 
} 

class B { 

    private String name; 

    @Autowired // Here we are injecting instance of Class A into class B so that you can use 'a' for accessing A's instance variables and methods. 
    A a; 

    private int roll; 

    // With setter and getter method 

    public void showDetail() { 
     System.out.println("Value of id form A class" + a.getId();); 
    } 
} 
+5

Esto no se compilará y generalmente es incorrecto. '@ Autowired' no significa que" puedes usar todas las funciones (método) y variables en la clase 'B' de la clase 'A'". Lo que hace es traer una instancia de 'A' en instancias de' B', por lo que puedes hacer 'a.getId()' de 'B'. –

+0

@dimadima Entonces, si hace System.out.println ("Valor de id form A class" + a.getId()) ;, y no como lo ha hecho, será más correcto. Por favor responda, ya que este es intuitivamente claro para mí y según mi nivel actual de comprensión está explicando Autowiring. –

+0

la anotación autocableada se introduce en la primavera 2.5 http://docs.spring.io/spring-framework/docs/2.5.x/api/org/springframework/beans/factory/annotation/Autowired.html – SpringLearner

6

@Autowired

  • marca un constructor, campo, método setter o método config como para ser autowired por instalaciones de inyección de dependencia de la primavera.

  • Sólo un constructor (al máximo) de cualquier clase de bean dado puede llevar este anotación, indicando el constructor para Autowire cuando se utiliza como un grano de primavera. Tal constructor no tiene que ser público.

  • Los campos se inyectan justo después de la construcción de un bean, antes de que se invoquen los métodos de configuración . Tal campo de configuración no tiene que ser público.

  • Los métodos de configuración pueden tener un nombre arbitrario y cualquier número de argumentos ; cada uno de esos argumentos se autoconectará con un bean correspondiente en el contenedor de Spring. Los métodos de establecimiento de propiedades de frijol son efectivamente solo un caso especial de dicho método de configuración general. Dichos métodos de configuración no tienen que ser públicos.

  • En el caso de métodos de argumentos múltiples, el parámetro 'required' es aplicable para todos los argumentos.

  • En el caso de un tipo de dependencia de Cobro o Mapa, el contenedor será y se conectará automáticamente a todos los beans que coincidan con el tipo de valor declarado. En el caso de un mapa , las claves se deben declarar como tipo String y se resolverán en con los nombres de los beans correspondientes.

3

sólo tiene que anotar sus UserServiceImpl de clase de servicio con la anotación

@Service("userService") 

contenedor de primavera se hará cargo del ciclo de vida de esta clase, ya que se registra como servicio.

Luego, en su controlador puede cablearlo automáticamente (instanciarlo) y usar su funcionalidad.

@Autowired 
UserService userService; 
6

¿Cómo funciona @Autowired work internally?

Ex -

class EnglishGreeting { 
    private Greeting greeting; 
    //setter and getter 
} 

class Greeting { 
    private String message; 
    //setter and getter 
} 

archivo .xml que se verá igual si no se usa @Autowired

<bean id="englishGreeting" class="com.bean.EnglishGreeting"> 
    <property name="greeting" ref="greeting"/> 
</bean> 

<bean id="greeting" class="com.bean.Greeting"> 
    <property name="message" value="Hello World"/> 
</bean> 

Si está utilizando @Autowired continuación

class EnglishGreeting { 
    @Autowired //so automatically based on the name it will identify the bean and inject. 
    private Greeting greeting; 
    //setter and getter 
} 

archivo .xml se se verán iguales si no se usa @Autowired

<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean> 

<bean id="greeting" class="com.bean.Greeting"> 
    <property name="message" value="Hello World"/> 
</bean> 

continuación Si todavía tiene alguna duda, pasar por debajo de demostración en vivo

How does @Autowired work internally ?

+0

Simplemente perfecto. – srk

0

Todo el concepto de inversión de control significa que están libres de una tarea para crear instancias de objetos de forma manual y proporcionar todas las dependencias necesarias. Cuando anota una clase con la anotación adecuada (por ejemplo, @Service), Spring creará automáticamente una instancia del objeto para usted. Si no está familiarizado con las anotaciones, también puede usar un archivo XML. Sin embargo, no es una mala idea crear instancias de clases manualmente (con la palabra clave new) en pruebas unitarias cuando no desea cargar todo el contexto de primavera.

1

La inyección de dependencia del resorte lo ayuda a eliminar el acoplamiento de sus clases. En lugar de crear objeto como éste

UserService userService = new UserServiceImpl(); 

Usted va a utilizar esto después de la introducción de DI

@Autowired 
private UserService userService; 

Para lograr esto es necesario crear un grano de su servicio en el archivo de ServiceConfiguration. Después de eso, debe Importar esa clase ServiceConfiguration a su clase WebApplicationConfiguration para que pueda Autowire ese bean en su Controlador de esta manera.

public class AccController { 

    @Autowired 
    private UserService userService; 
} 

puede encontrar un POC a base de configuración de Java aquí example

0

Tenga en cuenta que debe habilitar la anotación @Autowired añadiendo elemento <context:annotation-config/> en el archivo de configuración del resorte. Esto registrará el AutowiredAnnotationBeanPostProcessor que se encarga del procesamiento de la anotación.

Y luego puede conectar automáticamente su servicio utilizando el método de Inyección de campo.

public class YourController{ 

@Autowired 
private UserService userService; 

} 

yo encontramos este del poste Spring @autowired annotation

Cuestiones relacionadas