@Autowired Comparación de código nativo y Spring Principio de implementación del código fuente subyacente de Spring

El papel de la primavera

¿Qué problemas resolvió Spring después de su aparición? ¿Hay algún ejemplo de código específico?
Bold Style
Spring es un marco Java de código abierto que resuelve muchos problemas comunes en el desarrollo de aplicaciones empresariales, incluida la inyección de dependencias, la programación orientada a aspectos, la gestión de transacciones, el acceso a bases de datos, la seguridad, etc. Estos son algunos de los principales problemas que resuelve Spring junto con el código de muestra:

1. Inyección de dependencia (inyección de dependencia):

Spring permite desacoplar las dependencias entre objetos mediante la inyección de dependencias, lo que ayuda a que sea más fácil probar y mantener las aplicaciones.

// 示例:使用Spring进行依赖注入
@Service
public class MyService {
    
    
    private final MyRepository repository;

    @Autowired
     // 构造函数注入,通过构造函数接收 MyRepository 的实例
    public MyService(MyRepository repository) {
    
    
        this.repository = repository;
    }

    // ...
}

En el ejemplo anterior, @MyServiceel constructor de la clase recibe una @MyRepositoryinstancia como parámetro, así es como funciona la inyección del constructor. Cuando crea @MyServiceuna instancia, el contenedor Spring busca una @MyrRepositorydefinición de bean coincidente y la inyecta automáticamente en @MyServiceel constructor.

La inyección de constructor ayuda a garantizar que una clase tenga todas las dependencias necesarias cuando se crea una instancia, lo que hace que la clase sea más confiable y comprobable. Al mismo tiempo, también hace que las dependencias sean claramente visibles fuera de la clase, mejorando la legibilidad del código.

"Dependencia" en programación generalmente se refiere a un objeto que requiere los servicios o datos de otro objeto para realizar su trabajo. Cuando una clase (u objeto) depende de otra clase (u objeto), necesita hacer referencia (usar) una instancia de esa clase (u objeto) para realizar una operación específica.

En el marco Spring, las dependencias generalmente ocurren cuando un componente (por ejemplo, una clase de servicio o un controlador) necesita hacer referencia a instancias de otros componentes (por ejemplo, una clase de acceso a datos o una clase de servicio) para completar ciertas operaciones. Estas dependencias se pueden administrar e inyectar mediante inyección de constructor, inyección de método de establecimiento o inyección de campo.

El uso @Autowiredde anotaciones le dice a Spring que inyecte dependencias automáticamente, lo que significa que Spring se encarga de crear instancias de dependencias en tiempo de ejecución e inyectarlas en las clases que las requieren. Esto hace que el código sea más modular y esté débilmente acoplado, al tiempo que mejora la capacidad de mantenimiento y la capacidad de prueba.

Entonces, cuando se dice que una clase tiene dependencias, generalmente necesita hacer referencia a instancias de otras clases para completar su tarea. El mecanismo de inyección de dependencias de Spring ayuda a gestionar y resolver estas dependencias.

2. Programación Orientada a Aspectos:

Spring proporciona soporte AOP, que puede implementar fácilmente preocupaciones transversales, como registro, gestión de transacciones, etc.

// 示例:使用Spring AOP配置日志切面
@Aspect
@Component
public class LoggingAspect {
    
    
    @Before("execution(* com.example.service.*.*(..))")
    public void logMethodCall(JoinPoint joinPoint) {
    
    
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Calling method: " + methodName);
    }
}

3. Gestión de transacciones:

Spring simplifica la gestión de transacciones y puede realizar una gestión de transacciones declarativa mediante anotaciones o configuración XML.

// 示例:使用Spring注解配置声明式事务管理
@Service
public class MyService {
    
    
    @Autowired
    private MyRepository repository;

    @Transactional
    public void performTransactionalOperation() {
    
    
        // 执行数据库操作
    }
}

4. Acceso a la base de datos:

Spring proporciona plantillas JDBC e integración del marco de mapeo relacional de objetos (ORM) para simplificar el acceso y las operaciones de la base de datos.

// 示例:使用Spring JDBC模板执行查询
@Autowired
private JdbcTemplate jdbcTemplate;

public List<User> getAllUsers() {
    
    
    return jdbcTemplate.query("SELECT * FROM users", new BeanPropertyRowMapper<>(User.class));
}

5. Seguridad:

Spring Security es un subproyecto de Spring que proporciona un sólido mecanismo de autenticación y autorización para proteger aplicaciones.

// 示例:配置Spring Security以保护REST端点
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        http
            .authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasRole("USER")
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
}

Estos ejemplos son solo una pequeña parte de la funcionalidad proporcionada por el marco Spring. Spring tiene muchas otras características que se utilizan para resolver diversos problemas en el desarrollo de aplicaciones empresariales. Uno de los objetivos principales de Spring es mejorar la eficiencia del desarrollo y reducir la complejidad del código, facilitando a los desarrolladores la creación de aplicaciones escalables y mantenibles.

Comparación de dos códigos nativos

Cuando se trata del marco Spring, en comparación con el código Java nativo, Spring proporciona una forma más abstracta y de mayor nivel de resolver problemas para mejorar la eficiencia del desarrollo y la mantenibilidad. A continuación se muestran algunos ejemplos que comparan el código Java nativo con el código Spring:

1. Inyección de dependencia :

Java nativo :

public class MyService {
    
    
    private MyRepository repository;

    public MyService() {
    
    
        this.repository = new MyRepository();
    }

    // ...
}

Usando primavera :

@Service
public class MyService {
    
    
    private final MyRepository repository;

    @Autowired
    public MyService(MyRepository repository) {
    
    
        this.repository = repository;
    }

    // ...
}

Con Spring, puedes inyectar dependencias en una clase a través de anotaciones (como @Autowired) sin crear una instancia de ellas dentro de la clase. Esto facilita la gestión y el reemplazo de dependencias.

2. Programación orientada a aspectos :

Java nativo :

public class MyService {
    
    
    public void doSomething() {
    
    
        // 执行业务逻辑
        // 记录日志
        System.out.println("Logging: Method doSomething() is called.");
        // 处理事务
        try {
    
    
            // 开始事务
            // 执行业务逻辑
            // 提交事务
        } catch (Exception ex) {
    
    
            // 回滚事务
        }
    }
}

Usando primavera AOP :

@Aspect
@Component
public class LoggingAspect {
    
    
    @Before("execution(* com.example.service.MyService.*(..))")
    public void logMethodCall(JoinPoint joinPoint) {
    
    
        System.out.println("Calling method: " + joinPoint.getSignature().getName());
    }
}

Spring AOP le permite separar las preocupaciones transversales (como el registro y la gestión de transacciones) de la lógica empresarial y manejarlas mediante anotaciones o configuración XML.

3. Gestión de asuntos :

Java nativo :

public class MyService {
    
    
    public void performTransactionalOperation() {
    
    
        // 开始事务
        try {
    
    
            // 执行业务逻辑
            // 提交事务
        } catch (Exception ex) {
    
    
            // 回滚事务
        }
    }
}

Utilice la gestión de transacciones declarativas de Spring :

@Service
public class MyService {
    
    
    @Transactional
    public void performTransactionalOperation() {
    
    
        // 执行业务逻辑
    }
}

La gestión declarativa de transacciones de Spring le permite gestionar transacciones mediante anotaciones o configuración XML sin tener que escribir manualmente el código de gestión de transacciones.

4. Acceso a la base de datos :

Java nativo :

public class MyRepository {
    
    
    public List<User> getAllUsers() {
    
    
        // 使用JDBC连接数据库,执行查询等操作
        // 处理结果集
        // 关闭数据库连接
    }
}

Usando Spring JDBC :

@Autowired
private JdbcTemplate jdbcTemplate;

public List<User> getAllUsers() {
    
    
    return jdbcTemplate.query("SELECT * FROM users", new BeanPropertyRowMapper<>(User.class));
}

Las plantillas Spring JDBC proporcionan una forma más sencilla y segura de realizar operaciones de bases de datos, encapsulando detalles como la gestión de conexiones y el manejo de excepciones.

Estos ejemplos simplemente comparan algunos aspectos del código Java nativo y el código del marco Spring. Spring tiene como objetivo simplificar el desarrollo de aplicaciones empresariales, proporcionando un mayor nivel de abstracción y conveniencia, haciendo que el desarrollo sea más eficiente y mantenible. Pero tenga en cuenta que Spring no es necesariamente adecuado para todos los proyectos. La elección específica de utilizar Spring depende de las necesidades y la escala del proyecto.

@Autowired proceso detallado

Cuando se utiliza Spring Framework, @Autowiredlas anotaciones se utilizan para inyectar (o conectar) automáticamente dependencias en las clases. Esto significa que Spring se encarga de crear instancias de dependencias y pasarlas a las clases que las requieran, sin la necesidad de crear instancias de dependencias manualmente. Permítanme brindarles un ejemplo más detallado; espero que esta vez quede más claro:

Supongamos que tenemos una aplicación de gestión de usuarios sencilla con dos clases clave: UserServicey UserRepository. UserServiceNecesario UserRepositorypara obtener información del usuario.

  1. Crear clase de usuarioUser :
public class User {
    
    
    private String name;

    public User(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }
}
  1. Cree una clase de almacén de usuariosUserRepository , que simule la obtención de datos de usuario de la base de datos:
public class UserRepository {
    
    
    public List<User> getAllUsers() {
    
    
        // 模拟从数据库中获取用户数据
        return Arrays.asList(new User("Alice"), new User("Bob"));
    }
}
  1. Cree una clase de servicio de usuarioUserService que dependa UserRepositoryde recuperar datos de usuario:
public class UserService {
    
    
    private UserRepository userRepository;

    @Autowired // 使用 @Autowired 注解来告诉 Spring 自动注入依赖
    public UserService(UserRepository userRepository) {
    
    
        this.userRepository = userRepository;
    }

    public List<User> getAllUsers() {
    
    
        return userRepository.getAllUsers();
    }
}
  1. Configuración de Spring : para que @Autowiredlas anotaciones surtan efecto, Spring debe configurarse para escanear paquetes y realizar el ensamblaje automático.
@Configuration
@ComponentScan(basePackages = "com.example") // 告诉Spring扫描包路径以寻找组件
public class AppConfig {
    
    
    // 这个配置类用于启用注解扫描和自动装配
}
  1. Inicie la aplicación : en el punto de entrada de la aplicación, cree un contexto de aplicación Spring y obtenga UserServiceuna instancia de:
public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        // 创建Spring应用程序上下文,加载配置
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // 获取UserService实例,它会自动注入UserRepository
        UserService userService = context.getBean(UserService.class);

        // 调用UserService的方法来获取用户数据
        List<User> users = userService.getAllUsers();

        // 打印用户信息
        for (User user : users) {
    
    
            System.out.println("User: " + user.getName());
        }
    }
}

En este ejemplo, @Autowiredla anotación le dice a Spring que UserRepositoryla inyecte automáticamente en UserServiceel constructor. Este es el concepto central de la inyección de dependencia, que elimina la necesidad de que creemos manualmente UserRepositoryuna instancia, Spring la creará e inyectará automáticamente. Este enfoque ayuda a reducir el acoplamiento de su código, mejora la capacidad de mantenimiento y facilita las pruebas porque puede simular dependencias fácilmente.

Cómo funciona @Autowired

Explique con más detalle cómo @Autowiredfuncionan las anotaciones y la inyección automática de dependencias de Spring.

En el marco de Spring, @Autowiredlas anotaciones son una forma de inyectar automáticamente (autocableado) dependencias. Cuando marca una anotación en el constructor, la variable miembro, el método de establecimiento o el parámetro de método de una clase @Autowired, Spring se encarga de encontrar dependencias coincidentes en tiempo de ejecución e inyectarlas en la clase.

Ilustremos este proceso con un ejemplo.

Supongamos que existen las dos clases siguientes:

public class UserRepository {
    
    
    public List<User> getAllUsers() {
    
    
        // 模拟从数据库中获取用户数据
        return Arrays.asList(new User("Alice"), new User("Bob"));
    }
}

public class UserService {
    
    
    private UserRepository userRepository;

    @Autowired // 使用 @Autowired 注解来告诉 Spring 自动注入 userRepository 依赖
    public UserService(UserRepository userRepository) {
    
    
        this.userRepository = userRepository;
    }

    public List<User> getAllUsers() {
    
    
        return userRepository.getAllUsers();
    }
}

En el código anterior, UserServicela clase tiene una dependencia userRepository, que utiliza inyección de constructor. Al agregar una anotación al constructor @Autowired, le decimos a Spring que UserRepositoryinyecte la instancia en UserServiceél.

Cómo funciona la primavera:

Cuando crea un contexto de aplicación Spring y lo inicializa, Spring escanea todas las clases en la aplicación en busca de @Autowireddependencias marcadas por anotaciones e intenta resolver e inyectar automáticamente estas dependencias.

En este ejemplo, cuando llama context.getBean(UserService.class)para obtener UserServiceuna instancia de , Spring primero busca UserRepositoryuna instancia de y la crea. Luego, Spring UserRepositorypasará automáticamente la instancia al UserServiceconstructor porque el constructor está marcado con una @Autowiredanotación.

De esta manera, UserServicela clase tiene una userRepositoryinstancia que se puede usar para realizar operaciones de base de datos sin crear UserRepositoryuna instancia manualmente.

En resumen, @Autowiredlas anotaciones le dicen a Spring que inyecte automáticamente dependencias en las clases, simplificando así el proceso de gestión de dependencias y mejorando la capacidad de mantenimiento y prueba del código. Spring se encarga de crear e inyectar dependencias, haciendo que su código sea más modular y flexible. Si todavía tiene preguntas, no dude en preguntar.

Comparación de código nativo @AutoWired

Si no utiliza @Autowiredanotaciones Spring, puede utilizar código Java nativo para realizar manualmente la inyección de dependencia. Aquí hay un ejemplo simple que muestra cómo realizar la inyección del constructor manualmente en Java nativo:

Supongamos que existen las dos clases siguientes: UserServicey UserRepository.

public class UserRepository {
    
    
    public List<User> getAllUsers() {
    
    
        // 模拟从数据库中获取用户数据
        return Arrays.asList(new User("Alice"), new User("Bob"));
    }
}

public class UserService {
    
    
    private UserRepository userRepository;

    // 构造函数注入,手动传入 UserRepository 的实例
    public UserService(UserRepository userRepository) {
    
    
        this.userRepository = userRepository;
    }

    public List<User> getAllUsers() {
    
    
        return userRepository.getAllUsers();
    }
}

En este ejemplo, UserServiceel constructor de la clase acepta una UserRepositoryinstancia como parámetro y la inyección de dependencia se realiza manualmente. Cuando necesite una UserServiceinstancia creada, debe proporcionar una UserRepositoryinstancia adecuada:

public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        UserRepository userRepository = new UserRepository(); // 手动创建 UserRepository 实例
        UserService userService = new UserService(userRepository); // 手动注入 UserRepository 实例

        List<User> users = userService.getAllUsers();

        for (User user : users) {
    
    
            System.out.println("User: " + user.getName());
        }
    }
}

En Java nativo, es necesario crear y administrar manualmente instancias de dependencias y pasarlas a los constructores de las clases que las necesitan. Este método puede lograr la inyección de dependencias, pero en comparación con el uso de @Autowiredanotaciones de Spring, será más engorroso e inflexible, especialmente en aplicaciones complejas con una gran cantidad de dependencias. El mecanismo de inyección de dependencia de Spring simplifica enormemente este proceso y mejora la legibilidad y el mantenimiento del código.

Tres principios de implementación subyacentes de Spring

La función principal del marco Spring es la inyección de dependencia (DI), entre las cuales @Autowiredlas anotaciones son una de las claves para lograr la inyección de dependencia. Analicemos cómo el marco Spring subyacente encuentra y crea dependencias automáticamente.

1. Escaneo de rutas de clases y registro de componentes :

Cuando se inicia Spring, escanea la ruta del paquete especificado en busca de clases, especialmente aquellas marcadas con @Componentsus anotaciones derivadas (por ejemplo @Service, , @Repositoryetc.). Estas etiquetas indican que estas clases son componentes administrados por Spring. Spring registra estos componentes en un contenedor interno para la posterior inyección de dependencias y otras operaciones.

2. Definición de frijol :

En Spring, los componentes registrados se denominan beans. Cada Bean tiene una Definición de Bean asociada, que contiene metadatos sobre el Bean, como el nombre de la clase, el alcance, los parámetros del constructor, las propiedades y otra información.

3. Inyección de dependencia :

Cuando usa anotaciones en el constructor de una clase, variables miembro, métodos de establecimiento o parámetros de método @Autowired, Spring usa información en la definición del bean para determinar qué dependencias inyectar.

  • Inyección de constructor : si se usa en un constructor @Autowired, Spring buscará una definición de bean coincidente e inyectará el bean usando el constructor.

  • Inyección de variable miembro : si se usa en una variable miembro @Autowired, Spring establecerá el valor de la variable miembro a través de la reflexión e inyectará el Bean correspondiente en la variable miembro.

  • Inyección del método Setter : si se usa en el método Setter @Autowired, Spring llamará al método Setter e inyectará el Bean correspondiente en la propiedad.

  • Inyección de parámetros de método : si se usa en parámetros de método @Autowired, Spring buscará definiciones de beans coincidentes e inyectará los beans coincidentes en los parámetros del método.

4. Análisis de dependencia :

Spring usa información de las definiciones de beans para resolver dependencias. Comprueba cada lugar @Autowiredmarcado , luego encuentra la definición de bean coincidente, crea la instancia de bean correspondiente y la inyecta en el lugar requerido.

5. Procesamiento de dependencia circular :

Spring también maneja el caso de dependencias circulares. Si la clase A depende de la clase B y la clase B depende de la clase A, Spring utilizará objetos proxy para resolver esta dependencia circular y garantizar que cada bean se pueda crear normalmente.

6. Gestión del ciclo de vida del frijol :

Una vez que se inyecta la dependencia, Spring gestiona el ciclo de vida del bean, incluidas las fases de inicialización y destrucción.

En general, el marco Spring implementa @Autowiredla función de anotación a través de tecnologías como reflexión, definición de beans, escaneo de componentes y resolución de dependencias, lo que hace posible encontrar, crear e inyectar dependencias automáticamente. Este proceso se lleva a cabo en el contenedor principal de Spring e incluye principalmente la colaboración de componentes como ApplicationContexty BeanFactory. Aunque la implementación específica implica mucho código y detalles, la idea central de este proceso es manejar automáticamente las dependencias basadas en el escaneo de componentes, lo que hace que el desarrollo de aplicaciones sea más conveniente y modular.

Supongo que te gusta

Origin blog.csdn.net/qq_41398619/article/details/132706831
Recomendado
Clasificación