Preguntas de la entrevista de Complete Works of Java (15)

Preguntas de la entrevista de Complete Works of Java (15)

Baiyu es jaja

141. ¿Qué hace la clase DetachedCriteria en Hibernate?

Respuesta: El uso de DetachedCriteria y Criteria es básicamente el mismo, pero Criteria se crea mediante el método createCriteria () de Session, lo que significa que Criteria no se puede usar sin la Session que lo creó. DetachedCriteria se puede crear sin una sesión (utilizando el método DetachedCriteria.forClass ()), por lo que generalmente se denomina Criterio fuera de línea, y está vinculado a la sesión (llame a su método getExecutableCriteria (Session)) cuando se necesita la operación de consulta. Esto también significa que un DetachedCriteria se puede vincular a una sesión diferente cuando sea necesario.

142. ¿Cuál es la función del atributo mappedBy de la anotación @OneToMany?

Respuesta: @OneToMany se utiliza para configurar el mapeo de asociación de uno a muchos, pero en general, el mapeo de asociación de uno a varios lo mantienen varias partes, como estudiantes y clases. Los atributos de clase deben agregarse a la clase del estudiante para mantener a los estudiantes y Relación de asociación de clases (en la base de datos, el número de clase de clave externa en la tabla de estudiantes mantiene la relación de muchos a uno entre la tabla de estudiantes y la tabla de clases). Si desea utilizar la asociación de dos vías, agregue un atributo de contenedor a la clase de clase para almacenar los estudiantes, Y use la anotación @OneToMany para el mapeo, en este momento el atributo mappedBy es muy importante. Si usa XML para la configuración, puede usar la configuración inverse = "true" de la etiqueta <set> para lograr el mismo efecto.

143. ¿Cuál es la diferencia entre usar # y $ para escribir marcadores de posición en MyBatis?

Respuesta: # Trate los datos entrantes como una cadena y agregue automáticamente comillas a los datos entrantes; $ muestra los datos entrantes directamente en SQL. Nota: El uso del marcador de posición $ puede causar una inyección de SQL ***. No use $ donde pueda usar #. Debe usar $ en lugar de # al escribir cláusulas de orden por.

144. Explique el papel del espacio de nombres en MyBatis.

Respuesta: En proyectos grandes, puede haber una gran cantidad de sentencias SQL. En este momento, no es fácil asignar un identificador (ID) único a cada sentencia SQL. Para resolver este problema, en MyBatis, se puede establecer un espacio de nombres único para cada archivo de mapeo, de modo que cada declaración SQL definida en este archivo de mapeo se convierta en un ID definido en este espacio de nombres. Siempre que podamos asegurarnos de que este ID sea único en cada espacio de nombres, incluso si los ID de las sentencias en diferentes archivos de mapeo son los mismos, no habrá conflictos.

145. ¿Qué significa el SQL dinámico en MyBatis?

Respuesta: Para algunas consultas complejas, podemos especificar varias condiciones de consulta, pero estas condiciones pueden existir o no. Por ejemplo, al buscar una casa en la misma ciudad, podemos especificar el área, el piso y la ubicación para encontrar la casa. También es posible especificar el área, precio, tipo de casa y ubicación para encontrar la casa, en este momento es necesario generar dinámicamente declaraciones SQL según las condiciones especificadas por el usuario. Si no usamos el marco de la capa de persistencia, es posible que necesitemos ensamblar la instrucción SQL nosotros mismos. Afortunadamente, MyBatis proporciona funciones SQL dinámicas para resolver este problema. Los principales elementos que se utilizan para implementar SQL dinámico en MyBatis son:


- if 
- choose / when / otherwise 
- trim 
- where 
- set 
- foreach

A continuación se muestra un fragmento del archivo de mapeo.


<select id="foo" parameterType="Blog" resultType="Blog">
        select * from t_blog where 1 = 1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="content != null">
            and content = #{content}
        </if>
        <if test="owner != null">
            and owner = #{owner}
        </if>
   </select>

Por supuesto, también puede escribir como el siguiente.


 <select id="foo" parameterType="Blog" resultType="Blog">
        select * from t_blog where 1 = 1 
        <choose>
            <when test="title != null">
                and title = #{title}
            </when>
            <when test="content != null">
                and content = #{content}
            </when>
            <otherwise>
                and owner = "owner1"
            </otherwise>
        </choose>
    </select>

Eche un vistazo al siguiente ejemplo nuevamente.


<select id="bar" resultType="Blog">
        select * from t_blog where id in
        <foreach collection="array" index="index" 
            item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>

146. ¿Qué son IoC y DI? ¿Cómo se implementa DI?

Respuesta: IoC se llama Inversion of Control, que es la abreviatura de Inversion of Control. DI (Dependency Injection) se llama Dependency Injection, que es una interpretación más simple de IoC. La inversión del control es la transferencia de los derechos de llamada de los objetos tradicionalmente controlados directamente por el código del programa al contenedor, y el ensamblaje y la gestión de los componentes del objeto se realizan a través del contenedor. La llamada "inversión de control" es la transferencia de control sobre los objetos componentes, desde el propio código del programa al contenedor externo, y el contenedor crea objetos y gestiona las dependencias entre los objetos. IoC encarna el principio de Hollywood: "No me llames, nosotros te llamaremos". El principio básico de la inyección de dependencias es que los componentes de la aplicación no deben ser responsables de encontrar recursos u otros objetos cooperativos dependientes. El contenedor debe ser responsable de configurar el objeto, y la lógica para encontrar recursos debe extraerse del código del componente de la aplicación y entregarse al contenedor para completar. DI es una descripción más precisa de IoC, es decir, las dependencias entre componentes están determinadas por el contenedor en tiempo de ejecución. Para decirlo de manera más vívida, el contenedor inyecta dinámicamente ciertas dependencias en los componentes.
Por ejemplo: una clase A necesita usar métodos en la interfaz B, luego se debe establecer una asociación o relación de dependencia entre la clase A y la interfaz B. El método más primitivo es crear una instancia de la clase C que implemente la interfaz B en la clase A , Pero este método requiere que los desarrolladores mantengan la dependencia entre los dos, lo que significa que cuando la dependencia cambia, el código necesita ser modificado y todo el sistema reconstruido. Si gestiona estos objetos y sus dependencias a través de un contenedor, solo necesita definir el método (método constructor o setter) utilizado para asociar la interfaz B en la clase A, y poner la clase de implementación C de la clase A y la interfaz B en En el contenedor, la asociación entre los dos se realiza mediante la configuración del contenedor.

La inyección de dependencia se puede lograr a través de la inyección del método setter (inyección de configuración), inyección de constructor e inyección de interfaz. Spring admite la inyección de setter y la inyección de constructor. Por lo general, la inyección de constructor se usa para inyectar las dependencias necesarias. Para opcional Dependencia, la inyección de setter es una mejor opción La inyección de setter requiere que la clase proporcione un constructor sin parámetros o un método de fábrica estático sin parámetros para crear objetos.

147. ¿Cuáles son los alcances de Bean in Spring?

Respuesta: En la primera versión de Spring, solo hay dos ámbitos: singleton y prototype. El primero significa que el Bean existe como singleton; el segundo significa que cada vez que se llama al Bean desde el contenedor, se devolverá una nueva instancia, prototype. Normalmente traducido a prototipos.

Suplemento: También hay un modo de prototipo en el modo de creación en el modo de diseño. El modo de prototipo también es un modo de uso común. Por ejemplo, para hacer un software de diseño de interiores, todos los materiales están en la caja de herramientas, y cada vez que saca la caja de herramientas Un prototipo de un objeto material, el modo prototipo se puede realizar mediante la clonación de objetos.

En Spring 2.x, se agregaron tres nuevos ámbitos para WebApplicationContext, a saber: solicitud (se crea un nuevo bean para cada solicitud HTTP), sesión (la misma HttpSession comparte el mismo Bean y diferentes HttpSessions usan diferentes Beans) Y globalSession (la misma sesión global comparte un Bean).

Explicación: Tanto el modo singleton como el modo prototipo son patrones de diseño importantes. En general, una clase sin estado o estado inmutable es adecuada para el modo singleton. En el desarrollo tradicional, debido a que DAO contiene Connection, un objeto no seguro para subprocesos, no se usa el modo singleton; pero en el entorno Spring, todos los pares de clases DAO pueden adoptar el modo singleton, porque Spring usa AOP y ThreadLocal en Java API para no Los objetos a prueba de hilos se tratan especialmente.

ThreadLocal proporciona una nueva idea para resolver el problema de concurrencia de los programas multiproceso. ThreadLocal, como su nombre lo indica, es un objeto de subproceso localizado. Cuando un objeto que trabaja en varios subprocesos usa ThreadLocal para mantener variables, ThreadLocal asigna una copia de variable independiente para cada subproceso que usa la variable, por lo que cada subproceso se puede cambiar de forma independiente Una copia de sí mismo, sin afectar a las contrapartes de otros hilos. Desde la perspectiva del hilo, esta variable es como una variable local del hilo.
La clase ThreadLocal es muy simple y fácil de usar. Solo hay cuatro métodos, y se pueden usar los siguientes tres métodos:

  • void set (valor T): establece el valor de la variable local del hilo del hilo actual.
  • T get (): Obtiene el valor de la variable local del hilo correspondiente al hilo actual.
  • void remove (): Elimina el valor de la variable local del hilo en el hilo actual.
    ¿Cómo mantiene ThreadLocal una copia independiente de variables para cada hilo? Hay un mapa en la clase ThreadLocal, la clave es el objeto del hilo y el valor es una copia de la variable correspondiente al hilo. No es difícil simular una clase ThreadLocal por ti mismo. El código es el siguiente:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class MyThreadLocal<T> {
    private Map<Thread, T> map = Collections
       .synchronizedMap(new HashMap<Thread, T>());
    public void set(T newValue) {
        map.put(Thread.currentThread(), newValue);
    }
    public T get() {
        return map.get(Thread.currentThread());
    }
    public void remove() {
        map.remove(Thread.currentThread());
    }
}

148. Explique lo que se llama AOP (Programación Orientada a Aspectos).

Respuesta: AOP (Programación Orientada a Aspectos) se refiere a un paradigma de programación basado en una construcción de lenguaje llamada aspecto. Los aspectos son un nuevo mecanismo modular que se utiliza para describir La preocupación transversal en un objeto, clase o método.

149. ¿Cómo entiende el concepto de "atención transversal"?

Respuesta: La "atención transversal" afecta la función de atención de toda la aplicación. Es ortogonal a la lógica comercial normal y no tiene conexión necesaria, pero casi toda la lógica comercial involucra estas funciones de atención. Por lo general, preocupaciones como las transacciones, el registro y la seguridad son las preocupaciones transversales en la aplicación.

150. ¿Cómo entiende los conceptos de Joinpoint, Pointcut, Advice, Introducción, Weaving y Aspect en AOP?

Respuesta:
a. Punto de unión: una posición específica de ejecución del programa (por ejemplo, antes y después de que se llame a un método, después de que el método arroje una excepción). Una clase o un fragmento de código de programa tiene algunos puntos específicos con propiedades de límite, y los puntos específicos en estos códigos son puntos de conexión. Spring solo admite puntos de conexión de métodos.
b. Pointcut: si el punto de conexión es equivalente a un registro en los datos, entonces el pointcut es equivalente a la condición de consulta y un pointcut puede coincidir con múltiples puntos de conexión. El motor de análisis de reglas de Spring AOP es responsable de analizar las condiciones de consulta establecidas por el punto de corte y encontrar el punto de conexión correspondiente.
c. Mejora (aviso): La mejora es un fragmento de código de programa tejido en el punto de conexión de la clase de destino. Las interfaces mejoradas proporcionadas por Spring tienen nombres de ubicación, como BeforeAdvice, AfterReturningAdvice, ThrowsAdvice, etc. Muchos materiales han traducido mejoras en "notificaciones", lo que obviamente es una traducción insatisfactoria, que ha desconcertado a muchos programadores durante mucho tiempo.

Nota: Los consejos se traducen como "notificación" en muchos materiales escritos nacionales, pero obviamente esta traducción no puede expresar su esencia. Hay algunos materiales de lectura que traducen esta palabra como "mejorada". Esta traducción es más precisa para Consejos Interpretación, agregamos la función de atención transversal a la lógica comercial original a través de AOP. Esta es una mejora de la lógica comercial original. Esta mejora puede ser una mejora previa, una mejora posterior, una mejora posterior a la devolución y el lanzamiento de excepciones. Mejora del tiempo y mejora del entorno.

Introducción (Introducción): Introducción es una mejora especial que agrega algunos atributos y métodos a la clase. De esta manera, incluso si una clase empresarial no implementa originalmente una determinada interfaz, a través de la función de introducción, la lógica de implementación de la interfaz se puede agregar dinámicamente a la clase empresarial, de modo que la clase empresarial se convierta en la clase de implementación de esta interfaz.
e. Tejido: Tejido es el proceso de agregar mejoras a los puntos de conexión específicos de la clase objetivo. AOP tiene tres métodos de tejido: ① Tejido en tiempo de compilación: requiere un período especial de compilación de Java (por ejemplo, ajc de AspectJ); ②Tejido del período de carga: requiere el uso de un cargador de clases especial para mejorar la clase al cargar la clase; ③Tejido en tiempo de ejecución: genera un proxy para la clase objetivo para lograr una mejora en el tiempo de ejecución. Spring usa un proxy dinámico para implementar el tejido en tiempo de ejecución, mientras que AspectJ usa el tejido en tiempo de compilación y el tejido en tiempo de carga.
f) Aspecto: El aspecto está compuesto por puntos tangentes y realces (introducción), incluye la definición de la función de atención transversal y la definición del punto de conexión.

Suplemento: El modo proxy es uno de los patrones más clásicos entre los 23 patrones de diseño propuestos por GoF. El modo proxy es un modo estructural de objetos. Proporciona un objeto proxy para un objeto y el objeto proxy controla la referencia al objeto original. En pocas palabras, el objeto proxy puede realizar más responsabilidades que el objeto original. Cuando necesite agregar atención transversal al objeto original, puede usar el objeto proxy del objeto original. Cuando abrimos un documento de Word de la serie Office, si hay ilustraciones en el documento, cuando el documento se acaba de cargar, las ilustraciones en el documento son solo un marcador de posición con guiones. Cuando el usuario realmente pasa a una página y quiere ver la imagen, aparecerá Para cargar esta imagen, este es en realidad el uso del modo proxy. La caja virtual que reemplaza la imagen real es un proxy virtual; el método de carga de Hibernate también devuelve un objeto proxy virtual y espera que el usuario acceda a las propiedades del objeto antes de enviarlo a la base de datos. Emitir sentencias SQL para obtener objetos reales.

A continuación, se muestra un ejemplo de cómo encontrar un pistolero para realizar la prueba y demostrar el uso del modo proxy:


/**
 * 参考人员接口
 * @author 骆昊
 *
 */
public interface Candidate {
    /**
     * 答题
     */
    public void answerTheQuestions();
}

/**
 * 懒学生
 * @author 骆昊
 */
public class LazyStudent implements Candidate {
    private String name;        // 姓名
    public LazyStudent(String name) {
        this.name = name;
    }
    @Override
    public void answerTheQuestions() {
        // 懒学生只能写出自己的名字不会答题
        System.out.println("姓名: " + name);
    }
}

/**
 * 枪手
 * @author 骆昊
 */
public class Gunman implements Candidate {
    private Candidate target;   // 被代理对象
    public Gunman(Candidate target) {
        this.target = target;
    }
    @Override
    public void answerTheQuestions() {
        // 枪手要写上代考的学生的姓名
        target.answerTheQuestions();
        // 枪手要帮助懒学生答题并交卷
        System.out.println("奋笔疾书正确答案");
        System.out.println("交卷");
    }
}

public class ProxyTest1 {
    public static void main(String[] args) {
        Candidate c = new Gunman(new LazyStudent("王小二"));
        c.answerTheQuestions();
    }
}

Nota: A partir de JDK 1.3, Java proporciona tecnología de proxy dinámico, lo que permite a los desarrolladores crear instancias de proxy de interfaces en tiempo de ejecución, incluida la clase Proxy y la interfaz InvocationHandler. El siguiente ejemplo utiliza un proxy dinámico para escribir un proxy para ArrayList. Al agregar y eliminar elementos, los elementos agregados o eliminados y el tamaño de ArrayList se imprimen en la consola:


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
public class ListProxy<T>
 implements InvocationHandler {
    private List<T> target;
    public ListProxy(List<T> target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy,
           Method method, Object[] args)
            throws Throwable {
        Object retVal = null;
        System.out.println("[" + method.getName() + ": "
               + args[0] + "]");
        retVal = method.invoke(target, args);
        System.out.println("[size=" + target.size() + "]");
        return retVal;
    }
}

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ProxyTest2 {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        Class<?> clazz = list.getClass();
        ListProxy<String> myProxy = new ListProxy<String>(list);
        List<String> newList = (List<String>) 
                Proxy.newProxyInstance(clazz.getClassLoader(), 
                clazz.getInterfaces(), myProxy);
        newList.add("apple");
        newList.add("banana");
        newList.add("orange");
        newList.remove("banana");
    }
}

Nota: Una limitación del uso del proxy dinámico de Java es que la clase de proxy debe implementar la interfaz. Aunque la programación orientada a la interfaz es una regla que todo excelente programa Java conoce, la realidad a menudo no es satisfactoria. Para las clases que no implementan la interfaz ¿Cómo generar un proxy para ello? ¡heredar! La herencia es la forma más clásica de ampliar las capacidades del código existente. Aunque los principiantes a menudo abusan de la herencia, los programadores avanzados suelen ignorar la herencia. CGLib utiliza una tecnología de generación de código de bytes de muy bajo nivel para generar proxies mediante la creación de subclases para una clase. Complementa las deficiencias de los proxies dinámicos en Java. Por lo tanto, los proxies dinámicos y CGLib en Spring son medios importantes para crear proxies, que son útiles para implementar interfaces. La clase usa un proxy dinámico para generar una clase de proxy para ella, y la clase que no implementa la interfaz usa CGLib para crear un proxy a través de la herencia.

Supongo que te gusta

Origin blog.51cto.com/15061944/2593712
Recomendado
Clasificación