Comprender la inversión de control de SpringIoc y otro contenido: una entrada para principiantes

Algún día

Parte del contenido del artículo proviene de
https://gitee.com/zhongfucheng/Java3y#spring%E5%AE%B6%E6%97%8F
http://c.biancheng.net/view/4241.html

Fondo de nota

Cuando estaba aprendiendo Spring y jugando con el cubo familiar, descubrí que era un poco vago sobre el conocimiento básico de Spring, como IOC y AOP, inversión de control, inyección de dependencia, uso de anotaciones aún más simple, ensamblaje de Bean, etc., así que Escribí varios artículos en Internet. Algunos de los artículos en línea son abstractos y algunos ejemplos son brillantes pero abrumadores, por lo que debería escribir un artículo para aclarar lo que he aprendido.

Inyección de dependencia

Estudio de ejemplo

En el paquete com.mengma.ioc, cree dos interfaces, PersonDao, PersonDaoImpl, PersonService, PersonServiceImpl y FirstTest, dos clases de implementación, una clase de prueba y cinco archivos

package com.mengma.ioc;
public interface PersonDao {
    
    
    public void add();
}


package com.mengma.ioc;
public class PersonDaoImpl implements PersonDao {
    
    
    @Override
    public void add() {
    
    
        System.out.println("save()执行了...");
    }
}



package com.mengma.ioc;
public interface PersonService {
    
    
    public void addPerson();
}



package com.mengma.ioc;
public class PersonServiceImpl implements PersonService {
    
    
    // 定义接口声明
    private PersonDao personDao;
    // 提供set()方法,用于依赖注入
    public void setPersonDao(PersonDao personDao) {
    
    
        this.personDao = personDao;
    }
    // 实现PersonService接口的方法
    @Override
    public void addPerson() {
    
    
        personDao.add(); // 调用PersonDao中的add()方法
        System.out.println("addPerson()执行了...");
    }
}



@Test
public void test1() {
    
    
    // 定义Spring配置文件的路径
    String xmlPath = "applicationContext.xml";
    // 初始化Spring容器,加载配置文件
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
            xmlPath);
    // 通过容器获取personService实例
    PersonService personService = (PersonService) applicationContext
            .getBean("personService");
    // 调用personService的addPerson()方法
    personService.addPerson();
}

Dado que se especifica en la clase de prueba, el archivo applicationContext.xml también se crea en la carpeta ioc

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    <!-- 由 Spring容器创建该类的实例对象 -->
    <bean id="personDao" class="com.mengma.ioc.PersonDaoImpl" />
    <bean id="personService" class="com.mengma.ioc.PersonServiceImpl">
        <!-- 将personDao实例注入personService实例中 -->
        <property name="personDao" ref="personDao"/>
    </bean>
</beans>

Para ejecutar el programa, también se requieren los siguientes paquetes.
Inserte la descripción de la imagen aquí
Dirección de descarga del paquete 1: https://repo.spring.io/simple/libs-release-local/org/springframework/spring/3.2.2.RELEASE/

Dirección de descarga del paquete 2: http://commons.apache.org/proper/commons-logging/download_logging.cgi

Resultados de ejecución del programa En el
Inserte la descripción de la imagen aquí
código anterior, primero se declara el objeto personDao y se le agrega un método setter para la inyección de dependencia, y luego se implementa el método addPerson () de la interfaz PersonDao, y se llama al método save () y se emite una declaración en el método

Agregue un elemento al archivo de configuración applicationContext.xml para crear una instancia de la clase PersonServiceImpl e inyectar una instancia de personDao en personService

Se puede ver en el resultado de salida que después de usar el contenedor Spring para obtener una instancia de userService, se llama al método addPerson () de la instancia y en este método se llama al método add () en la clase de implementación PersonDao, y el resultado es la salida. Este es el método de inyección de establecedor de propiedades de contenedor Spring, y también es un método de inyección de dependencia comúnmente utilizado en el desarrollo real.

¿Por qué quieres hacer esto? ¿Por qué utilizar applicationContext, por qué utilizar Bean y por qué necesitamos la inyección de dependencias? Cual es el concepto?

abstracción

La inyección de dependencia (DI) y la inversión de control (Ioc) tienen el mismo significado, y son el mismo concepto descrito desde dos perspectivas.

Cuando una instancia de Java necesita otra instancia de Java, el método tradicional es que la persona que llama crea una instancia del destinatario (por ejemplo, utilizando la nueva palabra clave para obtener la instancia del destinatario), y después de usar el marco de Spring, la instancia del destinatario ya no se crea por la persona que llama, pero creado por el contenedor Spring, esto se llama inversión de control.

Cuando el contenedor Spring crea una instancia de la persona que llama, inyecta automáticamente la instancia de objeto que necesita la persona que llama a la persona que llama. De esta manera, la persona que llama obtiene la instancia de la persona que llama a través del contenedor Spring. Esto se denomina inyección de dependencia.

Puede entenderse simplemente como la inyección de dependencia es un método de implementación específico para lograr la inversión del control

Spring IOC resuelve el problema de la gestión de objetos y la dependencia de objetos:
tres torcidos

Originalmente, nuestros objetos son todos nuevos, pero si usamos Spring, entregaremos los objetos al "contenedor IOC" para su administración.

"Inversión de control" se refiere a: los objetos que originalmente eran nuevos "por nosotros mismos" ahora se entregan al contenedor IOC. Dar el "control" de este objeto a "otras partes". La "inversión del control" es más un patrón de pensamiento o diseño, que deja las cosas que están bajo el control de uno para que "otros" las manejen.

La "inyección de dependencia" se refiere más a la realización de la idea de "inversión de control": los objetos no necesitan crear o gestionar sus dependencias, y las dependencias se "inyectarán automáticamente" en los objetos que las necesiten.

La comprensión más simple de "inyección de dependencia" e "inversión de control": Originalmente, nuestros objetos son todos nuevos "por nosotros mismos". Ahora cedemos la autoridad de creación de este objeto y las dependencias entre los objetos al "contenedor IOC" Para administrar .

Ahora la pregunta es de nuevo, ¿por qué debemos entregar el objeto al "contenedor IOC" para administrarlo?

En teoría, también podemos considerar el "contenedor IOC" como una "fábrica". Las ventajas de utilizar IOC son:

Gestión centralizada de objetos para una fácil modificación

Reducir el grado de acoplamiento (la persona que llama no necesita ensamblarse ni preocuparse por la realización del objeto, simplemente sáquelo directamente del "contenedor IOC")

En este punto, tengo que hablar sobre el segundo concepto, contenedor Ioc

Contenedor IOC

IoC significa que en el desarrollo de programas, la creación de instancias ya no la gestiona el llamador, sino que la crea el contenedor Spring. El contenedor Spring es responsable de controlar la relación entre los programas, en lugar de ser controlado directamente por el código del programa. Por lo tanto, el control se transfiere del código del programa al contenedor Spring, y el control se invierte. Esta es la idea de IoC de Spring.

Spring proporciona dos contenedores de IoC, a saber, BeanFactory y ApplicationContext

¿Qué es un "contenedor IOC"? Podemos entenderlo como una "fábrica", y entregamos todos los objetos a esta "fábrica" ​​para que la gestione, incluida la creación de objetos y las dependencias entre objetos, etc. Cuando necesitamos usar el objeto, lo sacamos de esta "fábrica"

Generalmente, el ApplicationContext se usa comúnmente, que es el contexto de Spring

Es decir, reemplaza al programador para manipular el objeto, es decir, controla el ciclo de vida del Bean, es decir, el programador tiene la idea de "inversión de control" y la "inyección de dependencia" se la da al Bean. . Es el contexto Spring, y es parte del contenedor Ioc. Especies

Frijol

En el ejemplo anterior, el objeto Bean configurado en ApplicationContext.xml, en
general: usamos configuración XML + anotaciones para ensamblar muchos Beans, y las anotaciones representan la mayoría.

Después de poner el objeto en el "contenedor IOC", hay una relación entre el objeto y el objeto. Necesitamos decirle a Spring la dependencia entre los objetos y dejar que nos ayude a resolver la dependencia del objeto.

No pienses demasiado en la "relación entre objetos". En el desarrollo diario, de hecho, hay muchos atributos del objeto B en el objeto A.


La inyección de dependencia, como el mecanismo central de Spring, ha cambiado los hábitos de programación tradicionales. La aplicación ya no realiza la creación de instancias de componentes. En su lugar, se completa con el contenedor Spring, que se inyecta en la aplicación cuando es necesario, de modo que depender de las dependencias entre componentes. Todo esto es inseparable de los elementos utilizados en el archivo de configuración de Spring.

El contenedor Spring puede considerarse una gran fábrica, y el frijol en el contenedor Spring equivale al producto de la fábrica. Si desea que esta gran fábrica pueda producir y administrar Frijoles, debe indicarle al contenedor qué Frijoles se necesitan y cómo ensamblar estos Frijoles juntos.

Inserte la descripción de la imagen aquí

El primer Bean se configura a través del archivo xml, que contiene algunas etiquetas de atributos importantes, como id, nombre, clase, alcance, referencia, etc. Si es necesario, puede continuar aprendiendo más. Debido a la iteración de Spring, ahora hay más anotaciones Manera usada de configurar

Configuración de anotaciones

Daré un ejemplo y luego hablaré del concepto.

Estudio de ejemplo

En el paquete de com.mengma.annotation, cree dos interfaces, PersonDao, PersonDaoImpl, PersonService, PersonServiceImpl, PersonAction, AnnotationTest, dos clases de implementación, una clase de control y una clase de prueba. Seis archivos

package com.mengma.annotation;
public interface PersonDao {
    
    
    public void add();
}



package com.mengma.annotation;
import org.springframework.stereotype.Repository;
@Repository("personDao")
public class PersonDaoImpl implements PersonDao {
    
    
    @Override
    public void add() {
    
    
        System.out.println("Dao层的add()方法执行了...");
    }
}



package com.mengma.annotation;
public interface PersonService {
    
    
    public void add();
}



package com.mengma.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
@Service("personService")
public class PersonServiceImpl implements PersonService {
    
    
    @Resource(name = "personDao")
    private PersonDao personDao;
    public PersonDao getPersonDao() {
    
    
        return personDao;
    }
    @Override
    public void add() {
    
    
        personDao.add();// 调用personDao中的add()方法
        System.out.println("Service层的add()方法执行了...");
    }
}



package com.mengma.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
@Controller("personAction")
public class PersonAction {
    
    
    @Resource(name = "personService")
    private PersonService personService;
    public PersonService getPersonService() {
    
    
        return personService;
    }
    public void add() {
    
    
        personService.add(); // 调用personService中的add()方法
        System.out.println("Action层的add()方法执行了...");
    }
}



package com.mengma.annotation;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationTest {
    
    
    @Test
    public void test() {
    
    
        // 定义Spring配置文件路径
        String xmlPath = "com/mengma/annotation/applicationContext.xml";
        // 初始化Spring容器,加载配置文件,并对bean进行实例化
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                xmlPath);
        // 获得personAction实例
        PersonAction personAction = (PersonAction) applicationContext
                .getBean("personAction");
        // 调用personAction中的add()方法
        personAction.add();
    }
}

También debido a la configuración, el archivo applicationContext.xml se crea en la carpeta de anotaciones

<?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-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    <!--使用context命名空间,通知spring扫描指定目录,进行注解的解析-->
    <context:component-scan base-package="com.mengma.annotation"/>
</beans>

En el código anterior, primero use la anotación @Repository para identificar la clase PersonDaoImpl como un Bean en Spring, que es equivalente al archivo de configuración

<bean id = "personDao" class = “com.mengma.annotation.PersonDaoImpl” />

Escritura. Luego, genere una oración en el método add () para verificar si el método se llamó correctamente.

En el código anterior, primero use la anotación @Service para identificar la clase PersonServiceImpl como un Bean en Spring, que es equivalente al archivo de configuración

<bean id = "personService" class = “com.mengma.annotation.PersonServiceImpl” />

Escritura.

Luego use la anotación @Resource para marcar el atributo personDao (también se puede marcar en el método setPersonDao () de personDao), que es equivalente al archivo de configuración

<nombre de propiedad = "personDao" ref = "personDao" />

La redacción. Finalmente, llame al método add () en personDao en el método add () de esta clase y genere una oración.

En el código anterior, primero use la anotación @Controller para anotar la clase PersonAction, que es equivalente a escribir en el archivo de configuración

<bean id = "personAction" class = “com.mengma.annotation.PersonAction” />

Luego use la anotación @Resource para marcar personService, que es equivalente a escribir en el archivo de configuración

<propiedad nombre = "personService" ref = "personService" />。

Finalmente, se llama al método add () en personService en su método add () y se genera una oración.

Se puede ver en el resultado de salida que el método add () de la capa DAO, la capa de servicio y la capa de acción generan con éxito el resultado. Se puede ver que la forma de usar Annotation para ensamblar Bean se ha implementado con éxito

concepto

En Spring, aunque el uso de archivos de configuración XML puede lograr el ensamblaje de Beans, si el número de Beans en la aplicación es grande, los archivos de configuración XML estarán demasiado inflados, lo que traerá ciertas dificultades de mantenimiento y actualizaciones.

Java ha proporcionado la función de anotación (anotación) desde JDK 5.0, y Spring también proporciona un soporte completo para la tecnología de anotación. Una serie de anotaciones se definen en Spring 3. Las anotaciones más utilizadas son las siguientes.
@Component
puede usar esta anotación para describir Beans en Spring, pero es un concepto generalizado que solo representa un componente (Bean) y se puede aplicar en cualquier nivel. Cuando lo use, simplemente marque la anotación en la clase correspondiente.
@Repository se
usa para identificar la clase de capa de acceso a datos (capa DAO) como un Bean en Spring, y su función es la misma que @Component.
@Service
generalmente actúa en la capa empresarial (capa de servicio) y se usa para identificar la clase de la capa empresarial como un Bean en Spring, y su función es la misma que @Component.
@Controller
generalmente actúa sobre la capa de control (como Struts2 Action), que se usa para identificar la clase de capa de control como un Bean en Spring, y su función es la misma que @Component.
@Autowired se
utiliza para anotar las variables de atributo del Bean, el método Set y el constructor del atributo, y cooperar con el procesador de anotaciones correspondiente para completar la configuración automática del Bean. El montaje se realiza según el tipo de Bean por defecto.
@Resource tiene el
mismo efecto que Autowired. La diferencia es que @Autowired se ensambla por tipo de Bean por defecto, mientras que @Resource se ensambla por nombre de instancia de Bean por defecto.

Hay dos atributos importantes en @Resource: nombre y tipo.

Spring resuelve el atributo de nombre en el nombre de la instancia de Bean y el atributo de tipo en el tipo de instancia de Bean. Si se especifica el atributo de nombre, el ensamblaje se realiza de acuerdo con el nombre de la instancia; si se especifica el atributo de tipo, el ensamblaje se realiza de acuerdo con el tipo de bean.

Si no se especifica ninguno, primero se ensamblará de acuerdo con el nombre de la instancia de Bean, si no coincide, se ensamblará de acuerdo con el tipo de Bean; si no puede coincidir, se lanzará una NoSuchBeanDefinitionException.
Las
anotaciones @Qualifier y @Autowired se utilizan juntas, y el ensamblado predeterminado por tipo de Bean se modificará a ensamblado por el nombre de instancia del Bean. El nombre de instancia del Bean se especifica mediante el parámetro de la anotación @Qualifier.

Supongo que te gusta

Origin blog.csdn.net/weixin_43596589/article/details/112949217
Recomendado
Clasificación