一文搞懂 Spring 中的 IOC 容器到底是什么

1、Ioc概述:

IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。

Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。我们将由 IoC 容器管理的 Java 对象称为 Spring Bean,它与使用关键字 new 创建的 Java 对象没有任何区别。

IoC 容器是 Spring 框架中最重要的核心组件之一,它贯穿了 Spring 从诞生到成长的整个过程。

1.1、控制反转(IoC)

控制反转是一种思想,控制反转是为了降低程序的耦合度,提高程序扩展能力,控制反转就是将对象的创建权力转移出去,交给第三方容器去负责,将对象和对象之间的维护交给第三方容器管理。而控制反转又是通过DI(Dependency Injection):依赖注入实现的。

1.2、DI(Dependency Injection):依赖注入

DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想。

依赖注入:是指Spring在创建对象的过程中,将对象依赖属性通过配置的方式进行注入。

Spring依赖注入的方式主要有四个,基于注解注入方式、set注入方式、构造器注入方式、静态工厂注入方式。推荐使用基于注解注入方式,配置较少,比较方便

总结:DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想。

基于注解注入方式

Service层代码

@Service
public class AdminService {
    //code
}

Controller层代码

@Controller
@Scope("prototype")
public class AdminController {
​
    @Autowired
    private AdminService adminService;
​
    //code
}

@Autowired与@Resource都可以用来装配Bean,都可以写在字段、setter方法上。

区别:

@Autowired默认按类型进行自动装配(该注解属于Spring),默认情况下要求依赖对象必须存在,如果要允许为null,需设置required属性为false,例:@Autowired(required=false)。如果要使用名称进行装配,可以与@Qualifier注解一起使用。

    @Autowired
    @Qualifier("adminService")
    private AdminService adminService;

@Resource默认按照名称进行装配(该注解属于J2EE),名称可以通过name属性来指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行装配;如果注解写在setter方法上,默认取属性名进行装配。当找不到与名称相匹配的Bean时,会按照类型进行装配。但是,name属性一旦指定,就只会按照名称进行装配。

    @Resource(name = "adminService")
    private AdminService adminService;

 除此之外,对于一些复杂的装载Bean的时机,比如我们需要根据配置装载不同的Bean,以完成不同的操作,可以使用getBean(“beanID”)的方式来加载Bean。

通过BeanID加载Bean方法如下:

@Component
public class BeanUtils implements ApplicationContextAware {
​
    private static ApplicationContext applicationContext;
​
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        if (BeanUtils.applicationContext == null) {
            BeanUtils.applicationContext = applicationContext;
        }
    }
​
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
​
    public static Object getBean(String id) throws Exception {
        try {
            return applicationContext.containsBean(id) ? applicationContext.getBean(id) : null;
        } catch (BeansException e) {
            e.printStackTrace();
            throw new Exception("not found bean id: " + id);
        }
    }
}

我们在需要装载Bean的地方调用该方法即可

public class BaseController {
​
    protected IService loadService(String id) throws Exception {
        IService iService = (IService) BeanUtils.getBean(id);
        if (iService != null) {
            return iService;
        } else {
            throw new Exception("加载Bean错误");
        }
    }
}

2、面向切面编程(AOP):

2.1.AOP概念

在Spring 中,有两个核心概念,一个是IOC/DI , 一个是AOP,AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构。而OOP(Object Oriented PRogramming)面向对象编程,是以各种编程思想,所以,AOP也是一种编程思想,只是两者之间是不同的编程规范。

2.2.AOP作用

在不惊动原始设计的基础上为其进行功能增强。

2.3.AOP核心概念

  • 连接点(JoinPoint):程序执行过程中都任意位置,粒度为执行方法、抛出异常、设置变量等。

在SpringAOP中,理解为方法的执行

  • 切入点(Pointcut):匹配连接点的式子

在SpringAOP中,一个切入点可以描述一个具体方法,也可以匹配多个方法

连接点范围要比切入点范围大,是切入点的方法也一定是连接点,但是是连接点的方法就不一定要被增强,所以可能不是切入点

  •  通知(Advice):在切入点处执行的操作,也就是共性功能

在SpringAOP中,功能最终以方法的形式呈现

  • 通知类:定义通知的类​

  • 切面(Aspect):描述通知与切入点的对应关系

  • 连接点(可选择的所有英雄)

  • 切入点(已选择的英雄)

    通知(某个增益buff)

    通知类(所有增益buff)

    切面(带了buff的已选择英雄)

    2.4 AOP入门 

新建一个Maven项目,在pom.xml中添加依赖.

  <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.8</version>
        </dependency>
    </dependencies>

定义接口和实现类
在java包下添加BookDao和BookDaoImpl类(连接点)
public interface BookDao {
    public void save();
    public void update();
}
@Repository
public class BookDaoImpl implements BookDao {
 
    @Override
    public void save() {
        System.out.println(System.currentTimeMillis());
        System.out.println("book dao save ...");
    }
 
    @Override
    public void update() {
        System.out.println("book dao update ...");
    }
}

添加Spring配置类

@Configuration
@ComponentScan("com")
public class SpringConfig {
}

添加测试类

public class test {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
 
        BookDao bookDao = ctx.getBean(BookDao.class);
 
        bookDao.save();
        bookDao.update();
    }
}

项目结构如下:

定义通知类和通知

在com包下创建aop.MyAdvice类

public class MyAdvice {
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}

定义切入点 
public class MyAdvice {
    //定义切入点update()
    @Pointcut("execution(void com.dao.BookDao.update())")
    private void pt(){}
 
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}
制作切面

 切面是用来描述通知和切入点之间的关系

public class MyAdvice {
    //定义切入点update()
    @Pointcut("execution(void com.dao.BookDao.update())")
    private void pt(){}
 
    //制作切面
    @Before("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}

将通知类配给容器并标识其为切面类
@Component
@Aspect
public class MyAdvice {
    //定义切入点update()
    @Pointcut("execution(void com.dao.BookDao.update())")
    private void pt(){}
 
    //制作切面
    @Before("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}
开启注解格式AOP功能
@Configuration
@ComponentScan("com")
@EnableAspectJAutoProxy
public class SpringConfig {
}
运行测试

运行test测试类,控制台输出

        注:喜欢的朋友可以关注公众号“JAVA学习课堂”方便阅读,内容更丰富哦。

  • 24
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值