Spring IOC 和 AOP
文章目录
- Spring IOC 和 AOP
- 前言
- 什么是 IoC?
- **为什么叫控制反转**
- 不用IoC:所有对象开发者自己创建
- 使用IoC:对象不用卡法这创建,而是交给Spring框架完成
- 基于XML和基于注解
- 基于XML:
- 基于注解:
- IoC 解决了什么问题?
- 什么是 AOP?
- AOP 解决了什么问题?
- AOP 为什么叫做切面编程?
前言
Spring核心容器的主要组件是Bean工厂(BeanFactory),Bean工厂使用控制反转(IoC)模式来降低程序代码之间的耦合度,并提供了面向切面编程(AOP)的实现。
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的容器框架。
在具体介绍IoC和AOP之前,我们先简要说明下Spring常用注解
1、@Controller:用于标注控制器层组件
2、@Service:用于标注业务层组件
3、@Component : 用于标注这是一个受 Spring 管理的组件,组件引用名称是类名,第一个字母小写。可以使用@Component(“beanID”) 指定组件的名称
4、@Repository:用于标注数据访问组件,即DAO组件
5、@Bean:方法级别的注解,主要用在@Configuration和@Component注解的类里,@Bean注解的方法会产生一个Bean对象,该对象由Spring管理并放到IoC容器中。引用名称是方法名,也可以用@Bean(name = “beanID”)指定组件名
6、@Scope(“prototype”):将组件的范围设置为原型的(即多例)。保证每一个请求有一个单独的action来处理,避免action的线程问题。
由于Spring默认是单例的,只会创建一个action对象,每次访问都是同一个对象,容易产生并发问题,数据不安全。
7、@Autowired:默认按类型进行自动装配。在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
8、@Resource:默认按名称进行自动装配,当找不到与名称匹配的Bean时会按类型装配。
简单点说,就是,能够明确该类是一个控制器类组件的,就用@Controller;能够明确是一个服务类组件的,就用@Service;能够明确该类是一个数据访问组件的,就用@Repository;不知道他是啥或者不好区分他是啥,但是就是想让他动态装配的就用@Component。
@Controller、@Service、@Component、@Repository都是类级别的注解,如果一个方法也想动态装配,就用@Bean。
当我们想按类型进行自动装配时,就用@Autowired;当我们想按名称(beanID)进行自动装配时,就用@Resource;当我们需要根据比如配置信息等来动态装配不同的组件时,可以用getBean(“beanID”)。
什么是 IoC?
IOC是Spring全家桶各个功能模块的基础,创建对象的容器。
控制反转,将对象的创建进行反转,常规情况下,对象都是开发者手动创建的,使用IoC开发者不在需要创建对象,而是由IoC容器根据需求自动创建项目所需要的对象。
例如:现有类 A 依赖于类 B
- 传统的开发方式 :往往是在类 A 中手动通过 new 关键字来 new 一个 B 的对象出来
- 使用 IoC 思想的开发方式 :不通过 new 关键字来创建对象,而是通过 IoC 容器(Spring 框架) 来帮助我们实例化对象。我们需要哪个对象,直接从 IoC 容器里面过去即可。
为什么叫控制反转
控制 :指的是对象创建(实例化、管理)的权力
反转 :控制权交给外部环境(Spring 框架、IoC 容器)
不用IoC:所有对象开发者自己创建
使用IoC:对象不用卡法这创建,而是交给Spring框架完成
基于XML和基于注解
基于XML:
开发者把需要创建的对象在XML中进行配置,Spring框架读取这个配置文件,根据配置文件的内容来创建对象
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<bean class="com.southwind.ioc.DataConfig" id="config">
<property name="driverName" value="Driver"></property>
<property name="url" value="localhost:8080"></property>
<property name="username" value="root">
</property>
<property name="password" value="root">
</property>
</bean>
</beans>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
// DataConfig dataConfig = new DataConfig();
// dataConfig.setDriverName("Driver");
//dataConfig.setUrl("localhost:3306/dbname");
// dataConfig.setUsername("root");
// dataConfig.setPassword("root");
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
System.out.println(context.getBean("config"));
}
}
基于注解:
- 配置类(
@Configuration
)
用一个 Java 类来替代 XML 文件,把在 XML 中配置的内容放到配置类中。
import com.southwind.ioc.DataConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfiguration {
@Bean(value = "config")
public DataConfig dataConfig(){
DataConfig dataConfig = new DataConfig();
dataConfig.setDriverName("Driver");
dataConfig.setUrl("localhost:3306/dbname");
dataConfig.setUsername("root");
dataConfig.setPassword("root");
return dataConfig;
}
}
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfiguration.class);
System.out.println(context.getBean("config"));
- 扫包+配置
更简单的方式,不再需要依赖于 XML 或者配置类,而是直接将 bean 的创建交给目标类,在目标类添加注解来创建。
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component
public class DataConfig {
@Value("localhost:3306")
private String url;
@Value("Driver")
private String driverName;
@Value("root")
private String username;
@Value("root")
private String password;
}
ApplicationContext context = new AnnotationConfigApplicationContext("com.southwi
nd.ioc");
System.out.println(context.getBean(DataConfig.class));
自动创建对象,完成依赖注入
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component
public class GlobalConfig {
@Value("8080")
private String port;
@Value("/")
private String path;
@Autowired
private DataConfig dataConfig;
}
@Autowired 通过类型进行注入,如果需要通过名称取值,通过 @Qualifier 注解完成名称的映射
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component
public class GlobalConfig {
@Value("8080")
private String port;
@Value("/")
private String path;
@Autowired
@Qualifier("config")
private DataConfig dataConfig;
}
IoC 解决了什么问题?
IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。这样有什么好处呢?
- 对象之间的耦合度或者说依赖程度降低;
- 资源变的容易管理;比如你用 Spring 容器提供的话很容易就可以实现一个单例。
知乎参考帖
什么是 AOP?
AOP也是以IoC为基础,AOP是面向切面编程,抽象化的面向对象。
AOP:Aspect oriented programming 面向切面编程,AOP 是 OOP(面向对象编程)的一种延续。
面向切面编程,是一种抽象化的面向对象编程,对面向对象编程的一种补充,底层使用动态代理机制来实现。
主要解决的问题是:1. 打印日志 2. 事务 3. 权限处理
AOP 解决了什么问题?
通过上面的分析可以发现,AOP 主要用来解决:在不改变原有业务逻辑的情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。
AOP 为什么叫做切面编程?
切 :指的是横切逻辑,原有业务逻辑代码不动,只能操作横切逻辑代码,所以面向横切逻辑
面 :横切逻辑代码往往要影响的是很多个方法,每个方法如同一个点,多个点构成一个面。这里有一个面的概念
参考资料:
- 本文中加入的知乎链接
- B站楠哥学Java – 《两小时弄清楚Spring IOC 和 AOP》