Principio de implementación del COI de Spring

Lo que es SpringIOC
spring ioc se refiere a la inversión de control, el contenedor IOC es responsable de crear instancias, ubicar, configurar objetos en la aplicación y establecer dependencias entre estos objetos. Manejado por el contenedor Spring para una gestión unificada para lograr un acoplamiento suelto

La "inversión de control" no es una tecnología, sino una idea de diseño.

En el desarrollo de Java, Ioc significa entregar sus objetos diseñados al control del contenedor en lugar del control directo tradicional dentro de sus objetos. ¿Cómo entender a Ioc? La clave para entender Ioc es aclarar "Quién controla quién, qué controla, por qué es la inversión (cuando hay una inversión, debe haber un giro positivo) y qué aspectos se invierten", luego analicémoslo en profundidad:

● Quién controla quién, qué controla: en la programación tradicional de Java SE, creamos objetos directamente a través de nuevos dentro del objeto, el programa crea activamente objetos dependientes; y IoC tiene un contenedor especial para crear estos objetos, es decir, el contenedor Ioc Controla la creación de objetos; ¿quién controla a quién? Por supuesto, el contenedor IoC controla el objeto; ¿qué controles? Esto es principalmente para controlar la adquisición de recursos externos (no solo objetos, incluidos archivos, etc.).

● Por qué se invierte y qué aspectos se invierten: si hay inversión, hay rotación hacia adelante, las aplicaciones tradicionales son controladas activamente por nosotros mismos para obtener objetos dependientes directamente, que es la rotación hacia adelante; y el contenedor causa la inversión Para ayudar a crear e inyectar objetos dependientes, ¿por qué invertir? Debido a que el contenedor nos ayuda a encontrar e inyectar objetos dependientes, los objetos solo aceptan pasivamente los objetos dependientes, por lo que se invierte; ¿qué aspectos se invierten? La adquisición de objetos dependientes se invierte.

El principio de implementación del COI
utiliza un mecanismo de reflexión + tecnología XML

Después de comprender estos conceptos básicos, describimos brevemente todo el proceso a través de un diagrama esquemático simple,


Como se puede ver en el diagrama esquemático, cuando se inicia el contenedor web, el administrador global de beans de Spring irá al paquete escaneado en el archivo de configuración xml para obtener todas las clases y, de acuerdo con las anotaciones que utilice, encapsulará el correspondiente Gestionado en el contenedor global de beans. Una vez que se inicializa el contenedor, la información de objeto beanID y la clase de instanciación de bean existen. Ahora cuando necesitamos llamar a un método de otro bean en un servicio, solo necesitamos confiar en Simplemente inyecte el Id de otro bean. Cuando se llame, spring lo obtendrá del contenedor de bean inicializado. Si existe, le devolverá el objeto instanciado de la clase de bean dependiente, y puede llamar al dependiente Métodos relacionados o propiedades del frijol;

El siguiente es un código de ejemplo para simular el principio y el proceso de ejecución de todo el COI:
1. La estructura de demostración es la siguiente:


2. Archivos dependientes de Pom, aquí solo se necesitan las dependencias básicas de spring,

<propiedades>

<spring.version> 5.1.2.RELEASE </spring.version>
<project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
<project.reporting.outputEncoding> UTF-8 </project.reporting. outputEncoding>
<java.version> 1.8 </java.version>
</properties>

<dependencias>

<dependency>
<groupId> org.springframework </groupId>
<artifactId> spring-core </artifactId>
<version> $ {spring.version} </version>
</dependency>

<dependency>
<groupId> org.springframework </groupId>
<artifactId> spring-context </artifactId>
<version> $ {spring.version} </version>
</dependency>
<dependency>
<groupId> org.springframework < / groupId>
<artifactId> spring-aop </artifactId>
<version> $ {spring.version} </version>
</dependency>
<dependency>
<groupId> org.springframework </groupId>
<artifactId> spring-orm < / artifactId>
<version> $ {spring.version} </version>
</dependency>

<dependency>
<groupId> org.aspectj </groupId>
<artifactId> aspectjrt </artifactId>
<version> 1.6.1 </version>
</dependency>

<dependency>
<groupId> org.aspectj </groupId>
<artifactId> aspectjweaver </artifactId>
<version> 1.9.2 </version>
</dependency>


<! - https://mvnrepository.com/artifact/cglib/cglib ->
<dependency>
<groupId> cglib </groupId>
<artifactId> cglib </artifactId>
<versión> 3.2.10 </version>
< / dependencia>

<! - https://mvnrepository.com/artifact/com.mchange/c3p0 ->
<dependency>
<groupId> com.mchange </groupId>
<artifactId> c3p0 </artifactId>
<versión> 0.9.5.2 < / version>
</dependency>

<! - https://mvnrepository.com/artifact/mysql/mysql-connector-java ->
<dependency>
<groupId> mysql </groupId>
<artifactId> mysql-connector-java </artifactId>
<versión> 5.1.40 </version>
</dependency>

<! - https://mvnrepository.com/artifact/dom4j/dom4j ->
<dependency>
<groupId> dom4j </groupId>
<artifactId> dom4j </artifactId>
<versión> 1.6.1 </version>
< / dependencia>

</dependencies>

 

3. En primer lugar, personalizamos dos anotaciones: sabemos que @Service a menudo se usa en clases de negocios para marcar esta clase como una clase de gestión de beans, y @Autowired o @Resource se usan para la dependencia mutua entre beans.

// El servicio de anotación personalizada se inyecta en el contenedor de beans

@Target ({ElementType.TYPE})
@Retention (RetentionPolicy.RUNTIME)
public @interface SelfService {

}

 

// Simulación de anotación @Autowired

@Target ({TYPE, FIELD, METHOD})
@Retention (RUNTIME)
public @interface SelfAutowired {

}

 

4. Imite la clase de contenedor de bean de spring. Debo haber utilizado el siguiente código al realizar la prueba de integración en el marco de spring. La función de este código es simular la inicialización de un spring a través de esta clase. La clase de gestión de contenedores del bean. Todo el análisis y almacenamiento de la información del bean se llevará a cabo en esta clase. Escribamos una clase para restaurar este proceso.

SelfPathXmlApplicationContext app = new SelfPathXmlApplicationContext ("com.congge.service.impl");
1
clase personalizada de contenedor de bean spring,

/ **

  • Administrador de frijoles personalizado
  • @autor asus

* /
public class SelfPathXmlApplicationContext {

string StringName privado;

// Encapsula todos los contenedores de
beans private ConcurrentHashMap <String, Object> beans = null;

/ **
* Esta clase se carga cuando se crea
* @param packageName
* @throws Exception
* /
public SelfPathXmlApplicationContext (String packageName) lanza Exception {
beans = new ConcurrentHashMap <String, Object> ();
this.packageName = packageName;
initBeans ();
initEntryField ();
}

/ **
* Inicializa todas las propiedades del objeto de instancia de bean
* @throws Exception
* /
private void initEntryField () lanza Exception {
// 1. Atraviesa todos los objetos contenedor de bean
para (Entry <String, Object> entry: beans.entrySet ( )) {
// 2. Determine si hay una anotación en la propiedad
Object bean = entry.getValue ();
attriAssign (bean);
}
}

/ **
* Obtener el nombre del bean según beanId
* @param beanId
* @return
* @throws Exception
* /
public Object getBean (String beanId) lanza Exception {
if (StringUtils.isEmpty (beanId)) {
throw new Exception ("el parámetro beanId no puede Está vacío ");
}
// 1. Obtener bean
Object object = beans.get (beanId);
// attriAssign (object);
return object;
} del contenedor spring

/ **
* Obtener todos los beans bajo el paquete de escaneo
* /
private void initBeans () lanza la excepción {
// 1. Use el mecanismo de reflexión de java para escanear el paquete, [obtener todas las clases bajo el paquete actual]
Lista <Clase <? >> clases = ClassParseUtil.getClasses (packageName);
// 2. Determine si la anotación del bean inyectado existe en la clase
ConcurrentHashMap <String, Object> classExisAnnotation = findClassExisAnnotation (classes);
if (classExisAnnotation == null || classExisAnnotation.isEmpty () {)
lanzar una nueva excepción ("No hay clases con anotaciones en este paquete");
}

}

/ **
* Juzgue si hay anotaciones para inyectar beans personalizados en la clase
* @param classes
* @return
* @throws Exception
* /
public ConcurrentHashMap <String, Object> findClassExisAnnotation (List <Class <? >> classes) lanza Exception {
for (Class <?> classInfo: classes) {
// Determine si hay una anotación en la clase [Obtener anotación de servicio personalizada]
SelfService annotation = classInfo.getAnnotation (SelfService.class);
if (annotation! = null) {
// Get El nombre de clase de la clase actual
String className = classInfo.getSimpleName ();
String beanId = toLowerCaseFirstOne (className);
Object newInstance = newInstance (classInfo);
beans.put (beanId, newInstance);
}

}
devolver frijoles;
}

// 首 字母 转 小写 Public
static String toLowerCaseFirstOne (String s) {
if (Character.isLowerCase (s.charAt (0)))
return s;
de lo contrario
return (new StringBuilder ()). append (Character.toLowerCase (s.charAt (0))). append (s.substring (1)). toString ();
}

/ **
* Obtener el objeto instanciado de la clase por nombre de clase
* @param classInfo
* @return
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* /
public Object newInstance (Class <?> ClassInfo)
lanza ClassNotFoundException, InstantiationException, IllegalAccessException {
return classInfo.newInstance ();
}

/ **
* Principio de anotación de inyección de dependencia
* @param object
* @throws Exception
* /
public void attriAssign (Object object) lanza Exception {

// 1. Use el mecanismo de reflexión para obtener todos los atributos de la clase actual
Class <? Extend Object> classInfo = object.getClass ();
Field [] declaraciónFields = classInfo.getDeclaredFields ();

// 2. Determine si hay una anotación
para el atributo de clase actual para (Campo campo: declaradoFields) {
SelfAutowired extResource = field.getAnnotation (SelfAutowired.class);
if (extResource! = Null) {
// Obtenga el nombre del atributo
String beanId = field.getName ();
objeto = el frijol getBean (el beanId);
(! frijol = null) {SI
// nombre del atributo predeterminado 3. Encuentre el depósito de granos de objeto 1 parámetro 2 parámetro cesionarios de objetos actuales ellas
field.setAccessible (true); // Permitir acceso a propiedades privadas
field.set (object, bean);
            }
        }
   }

}

}

Cuando esta clase se inicializa, a través de los dos métodos en el constructor, el nombre del paquete especificado se pasa externamente y se analizan todas las clases y las anotaciones relacionadas en el paquete. El principio de implementación es principalmente utilizar la reflexión.

 

 

 

Después de obtener la colección instanciada de todas las clases a través de una clase de herramienta, recorremos esta colección. Para el método de ejecución específico, consulte el método findClassExisAnnotation.

 

 

 

En el método findClassExisAnnotation, podemos ver que usamos anotaciones personalizadas para que coincida con este objeto de clase de instancia. Si las anotaciones correspondientes coinciden, el bean se encapsula en la colección global. ConcurrentHashMap se usa aquí para la encapsulación.

 

 

 

 


Una vez completado este paso, los objetos de clase relacionados, incluida la anotación personalizada [@Service], se almacenan en la colección de memoria. Si usa sus propios beans después de iniciar el contenedor web, puede ir directamente al contenedor a través del método getBean. Solo obténgalo directamente, puede obtener el objeto instanciado de la clase correspondiente al beanId actual a través de este método, puede usar los métodos relacionados en el interior,

 

 

 

 


Pero aquí no está terminado, si tenemos una anotación como la siguiente en una clase marcada con @Service, que depende de algún otro bean, por ejemplo, en nuestra clase userService depende de orderService, se forma La llamada inyección de dependencia,

 

 

 

 


Del mismo modo, la inyección de dependencia también se realiza de la misma manera que antes, inmediatamente después del final del método initBean (), echemos un vistazo a este método,

 

 

 

 

En el método initEntryField (), lo que hay que hacer es atravesar todos los beans inicializados arriba y luego ir al objeto de instancia de cada bean para analizar y encapsular la información correspondiente sobre el atributo. Veamos el método initEntryField ().

 

 

 

 

 

 

 


Mediante este método, puede encapsular la información de otros beans que dependen de un bean,

/ **
* Principio de implementación de la anotación de inyección de dependencia
* @param object
* @throws Exception
* /
public void attriAssign (Object object) lanza Exception {

// 1. Use el mecanismo de reflexión para obtener todos los atributos de la clase actual
Class <? Extend Object> classInfo = object.getClass ();
Field [] declaraciónFields = classInfo.getDeclaredFields ();

// 2. Determine si hay una anotación
para el atributo de clase actual para (Campo campo: declaradoFields) {
SelfAutowired extResource = field.getAnnotation (SelfAutowired.class);
if (extResource! = Null) {
// Obtenga el nombre del atributo
String beanId = field.getName ();
objeto = el frijol getBean (el beanId);
(! frijol = null) {SI
// nombre del atributo predeterminado 3. Encuentre el depósito de granos de objeto 1 parámetro 2 parámetro cesionarios de objetos actuales ellas
field.setAccessible (true); // Permitir acceso a propiedades privadas
field.set (object, bean);
         }
      }
   }

}

 

Finalmente, escribimos una clase de prueba para verificar, ejecutar directamente la función principal a continuación,

 

Prueba de clase pública1 {

pública principal static void (String [] args) throws Exception {

SelfPathXmlApplicationContext App = new nueva SelfPathXmlApplicationContext ( "com.congge.service.impl");
UserServiceImpl UserServiceImpl = (UserServiceImpl) app.getBean ( "UserServiceImpl");
cadenaresult = UserServiceImpl. add ();
System.out.println ("Obtener el resultado de ejecución de orderService es:" + result);
System.out.println ("El objeto de instancia de bean actual es:" + userServiceImpl);
}

} Puede ver que nuestro contenedor personalizado de frijoles ha tenido efecto

 

 

 Finalmente, se adjunta el código fuente y los socios pequeños que lo necesitan pueden descargarlo por sí mismos, https://download.csdn.net/download/zhangcongyi420/11131211

Declaración de derechos de autor: Este artículo es un artículo original del blogger de CSDN "Mysterious Onion", que sigue el acuerdo de derechos de autor CC 4.0 BY-SA. Adjunte el enlace original y esta declaración para su reimpresión.
Enlace original: https://blog.csdn.net/zhangcongyi420/article/details/89419715

Supongo que te gusta

Origin www.cnblogs.com/langcangsheng/p/12759165.html
Recomendado
Clasificación