• spring:详解控制反转IOC和AOP


    IOC

    IOC (Inversion of Control)是Spring的核心概念之一。它是指控制反转,它改变了程序员的编程习惯,将应用程序的控制权从应用程序代码中转移到IoC容器中,使应用程序变得更加灵活和易于维护。Spring中的IoC容器充当了控制权的中心,通过配置文件或注解,容器将对象实例化、组装和配置,然后将它们提供给应用程序代码使用。

    DI:Dependency Injection,中文意思是依赖注入。依赖注入(DI)是实现控制反转的一种方式,它通过容器自动将所需的依赖关系注入到对象中,从而实现对象之间的解耦。在Spring中,依赖注入可以通过XML配置文件或注解方式来实现。

    关于XML方式和注解的方式创建和使用java bean,我们一般使用注解的方式,java bean 可以理解为 js 中的对象,类似这样:

    package cn.itcast.domain;
    
    public class User {
        private int id;
        private String name;
        private int age;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    作用:解耦

    我结合我常用 js 的方式说一下我理解的IOC,在 js 中我们习惯用函数式编程来解耦我们的程序,函数式其实就是让依赖由函数传入,而不是在函数内部获取。其实和IOC一样,IOC也是让依赖从外部获取,这里的注入的依赖 userService
    @Autowired
    private UserService userService;
    其实就是js函数里的形参 function (userService) {}。

    工厂模式

    本来我们直接用 new 的方式会让 app 和资源是直接依赖的无法消除,而使用 ioc 我们让 app 问工厂要资源,工厂去控制资源的调度。这种控制权发生的转移我们就叫控制反转。
    在这里插入图片描述

    实例

    例如,假设我们有一个名为UserService的类,它需要与数据访问对象(DAO)进行交互。如果我们将UserService与DAO紧密耦合在一起,那么每次需要修改数据访问的实现时,就需要修改UserService的实现。而如果我们使用控制反转,则可以将DAO的实现作为一个bean注入到UserService中,这样UserService只需要关注其需要的数据访问操作,而不需要关注具体的DAO实现。

    @Service  
    public class UserService {  
      
        @Autowired  
        private UserDao userDao;  
      
        public List<User> getAllUsers() {  
            return userDao.getAll();  
        }  
      
        public User getUserById(int id) {  
            return userDao.getUserById(id);  
        }  
      
        // Other methods...  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在上述代码中,UserService类通过@Autowired注解将UserDao类的实例注入到自身中,从而避免了直接在UserService类中创建UserDao实例。这是控制反转的一个基本例子,它通过将对象的创建和管理交给了Spring容器来降低类之间的耦合度。

    基于xml管理Bean

    一般很少用

    基于注解管理Bean

    注解的概念:和XML文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。

    但是追根本源:所有一切的操作都是由Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行。

    常用注解:用于创建对象的

    使用@Component注解标记普通组件(相当于在 xml 中配置一个 bean,属性
    value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。)

    import org.springframework.stereotype.Component;
    
    @Component
    public class CommonComponent {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用@Repository注解标记持久化层组件

    import org.springframework.stereotype.Repository;
    
    @Repository
    public class UserDaoImpl implements UserDao {
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用@Service注解标记业务逻辑组件

    import org.springframework.stereotype.Service;
    
    @Service
    public class UserServiceImpl implements UserService {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用@Controller注解标记控制层组件

    import org.springframework.stereotype.Controller;@Controller
    public class UserController {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我们可以点进去查看源码,我们会发现:@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。对于Spring的IOC容器来说,这三个组件本质上没有什么区别,而他们的的作用主要是来提高代码的可读性。

    常用注解:用于注入数据的

    @Autowired、@Qualifier、@Resource和@Value是Spring框架中常见的注解,它们的区别主要有以下几点:

    @Autowired和@Qualifier:这两个注解都是Spring的注解,用于自动装配bean。@Autowired用于自动装配bean,@Qualifier用于指定在存在多个相同类型的bean时,注入哪一个bean。
    @Resource:这个注解属于J2EE的注解,用于自动装配bean。默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。使用这个注解,需要在J2EE环境中才能使用。
    @Value:这个注解是Spring框架的注解,用于注入基本类型和String类型的值。这个注解有一个value属性,用于指定数据的值。可以使用Spring中的SpEL(也就是Spring的EL表达式)来定义复杂的表达式。这个注解不能用于装配bean,只能用于注入值。
    总结起来,这四个注解的作用各不相同,@Autowired和@Qualifier主要用于自动装配bean,@Resource主要用于在J2EE环境中自动装配bean,而@Value主要用于注入基本类型和String类型的值。

    在成员变量上使用@Autowired注解来完成自动装配
    在controller层装配Service

    @Controller
    public class UserController {
    
        @Autowired
        private UserService userService;
        public void add(){
            userService.add();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这个例子中,我们有两个同类型的SomeService bean,通过@Qualifier注解指定我们想要注入的bean的名称。

    @Configuration  
    public class AppConfig {  
      
        @Bean  
        @Qualifier("someService1")  
        public SomeService someService1() {  
            return new SomeService();  
        }  
      
        @Bean  
        @Qualifier("someService2")  
        public SomeService someService2() {  
            return new SomeService();  
        }  
      
        @Autowired  
        @Qualifier("someService2")  
        private SomeService someService;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    常用注解:和生命周期相关的(了解)

    @PostConstruct:用于指定初始化方法。
    @PreDestroy:用于指定销毁方法。

    常用注解:新注解

    @ComponentScan
    用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
    是一样的。

    @Configuration
    @ComponentScan("com.itheima")
    public class SpringConfiguration {
    }
    
    • 1
    • 2
    • 3
    • 4

    我们已经配置好了要扫描的包,但是数据源和 JdbcTemplate 对象如何从配置文件中移除呢?

    @Bean:
    该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。

    @PropertySource:
    用 于 加载 .properties 文件 中的 配置 。 例如 我们 配置 数据 源时 , 可以 把连 接数 据库 的信 息 写 到
    properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
    属性:
    value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:

    public class JdbcConfig {
    	@Value("${jdbc.driver}")
    	private String driver;
    	@Value("${jdbc.url}")
    	private String url;
    	@Value("${jdbc.username}")
    	private String username;
    	@Value("${jdbc.password}")
    	private String password;
    	/**
    	* 创建一个数据源,并存入 spring 容器中
    	* @return
    	*/
    	@Bean(name="dataSource")
    	public DataSource createDataSource() {}
    }
    jdbc.properties 文件:
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/day44_ee247_spring
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    CSS3与HTML5
    《Java并发编程之美》读书笔记——ThreadLocalRandom类原理剖析
    数据结构——栈的讲解(超详细)
    既然测试也要求写代码,那干脆让开发兼任测试不就好了吗?
    OpenCL编程指南-9.3使用事件完成评测、内核中的事件、OpenCL外部的事件
    技术专家说 | 如何基于 Spark 和 Z-Order 实现企业级离线数仓降本提效?
    java毕业设计爱心互助及物品回收管理系统Mybatis+系统+数据库+调试部署
    Vue中的$attrs和inheritAttrs
    BinomialTree 二叉树
    【VASP】POSCAR文件
  • 原文地址:https://blog.csdn.net/weixin_43972437/article/details/133742884