Spring IoC 与 AOP 的基本概念
·
Spring IoC 与 AOP 的基本概念
一、 IoC
IoC (inversion of control) 控制反转:将对象的创建进行反转,常规情况下,对象都是由开发者手动创建的,使用 IoC,开发者不再需要创建对象,而是由 IoC 容器 根据需求自动创建项目所需要的对象。
不用 IoC:所有对象由开发者手动创建
使用 IoC:对象不在由开发者创建,而是由 Spring 框架完成
普通人找对象需要主动付出,而皇帝找对象只需在后宫三千中选择。所以说 IoC 给予了开发者皇帝般的享受。
1. pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.15</version>
</dependency>
2. 配置要让 Spring 框架创建的对象
方法1:基于 XML;方法2:基于注解
准备一个类
@Data // lombok注解之一,用于生成 get 和 set 方法
public class DataConfig {
private String url;
private String driverName;
private String username;
private String password;
}
2.1 基于 XML
开发者把需要交给Spring框架创建的对象在 XML 中进行配置,Spring 框架读取这个配置文件,根据配置文件的内容来创建对象
2.1.1 在 resources 目录下创建 spring.xml (名称任意),并配置对象
<beans>
<!--创建一个名字为 config 的 DataConfig 的对象-->
<bean class="com.mohanqing.ioc.DataConfig" id="config">
<!-- 给属性赋值 -->
<property name="driverName" value="Driver"></property>
<property name="url" value="localhost:3306/mohanqing"></property>
<property name="password" value="1234"></property>
</bean>
</beans>
2.1.2 获取对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); // IoC 容器
System.out.println(context.getBean("config")); // 通过名字获取
2.2 基于注解
方法1:配置类;方法2:注解 + 扫包
2.2.1 配置类
用一个 Java 类来替代 XML 文件,把在 XML 中配置的内容放到配置类中
@Configuration // 配置类注解
public class BeanConfiguration { // 这个类相当于 XML 文件
//@Bean // 这个方法相当于 XML 文件中的 <bean>,默认 id 为方法名 dataConfig
@Bean(value = "config") // 自定义 id,也可以使用 name = "config"
public DataConfig dataConfig(){
DataConfig dataConfig = new DataConfig();
dataConfig.setDriverName("Driver");
dataConfig.setUrl("localhost:3306/mohanqing");
dataConfig.setUsername("root");
dataConfig.setPassword("1234")
return dataConfig;
}
}
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfiguration.class);
System.out.println(context.getBean(DataConfig.class)); // 通过类型获取
// System.out.println(context.getBean("dataConfig")); // 通过默认 id(方法名)获取
System.out.println(context.getBean("config")); // 通过自定义的 id 获取
// ApplicationContext context = new AnnotationConfigApplicationContext("com.mohanqing.configuration"); // 扫包
// System.out.println(context.getBean("config"));
2.2.2 注解 + 扫包
不需要配置类,而是直接将 bean 的创建交给目标类,在目标类添加注解
@Data
@Component // 将这个类交给 IoC 容器管理,创建这个类的对象
public class DataConfig {
@Value("localhost:3306/mohanqing") // 赋值
private String url;
@Value("Driver")
private String driverName;
@Value("root")
private String username;
@Value("1234")
private String password;
}
ApplicationContext context = new AnnotationConfigApplicationContext("com.mohanqing.ioc"); // 扫描这个包下的所有类,如果类上有 @Component, 就会被注入到 IoC 中
System.out.println(context.getBean(DataConfig.class)); // 通过类型获取
依赖注入
A 中有 B,创建 A对象 和 B对象,自动的将 B 装入 A 中
@Data
@Component
public class GlobalConfig {
@Value("8080")
private String port;
@Value("/")
private String path;
@Autowired // 自动装配,通过类型注入
private DataConfig dataConfig;
}
ApplicationContext context = new AnnotationConfigApplicationContext("com.mohanqing.ioc");
System.out.println(context.getBean(GlobalConfig.class)); // 通过类型获取
@Autowired 通过类型进行注入,如果需要通过名称取值,则需要通过 @Qualifier 完成名称的映射
@Data
@Component
public class GlobalConfig {
@Value("8080")
private String port;
@Value("/")
private String path;
@Autowired
@Qualifier("config")
private DataConfig config;
}
@Data
@Component("config") // 指定名称
public class DataConfig {
@Value("localhost:3306/mohanqing")
private String url;
@Value("Driver")
private String driverName;
@Value("root")
private String username;
@Value("1234")
private String password;
}
二、AOP
AOP (Aspect-Oriented Programming) 面向切面编程,一种抽象化的面向对象编程
1. 没有 AOP 时
没有AOP时的程序核心业务逻辑和其它的非业务代码耦合在一起

public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
System.out.println("add方法的参数是[" + num1 + "," + num2 + "]");
int result = num1 + num2;
System.out.println("add方法的结果是" + result);
return result;
}
@Override
public int sub(int num1, int num2) {
System.out.println("sub方法的参数是[" + num1 + "," + num2 + "]");
int result = num1 - num2;
System.out.println("sub方法的结果是" + result);
return result;
}
}
问题:每个方法都包含相同的横切关注点代码(权限、日志、事务等)
2. 有 AOP 时
AOP 把切面抽象成对象,做到核心业务和非业务代码的解耦合

AOP 底层使用动态代理机制

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.15</version>
</dependency>
// 核心业务类(只关注业务)
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1 + num2;
return result;
}
@Override
public int sub(int num1, int num2) {
int result = num1 - num2;
return result;
}
}
// 切面类(处理横切关注点)
@Aspect // 声明为切面
@Component // 注入 IOC
public class LoggerAspect {
@Before("execution(public int com.mohanqing.aop.CalImpl.*(..))") // 目标方法执行之前
public void before(JoinPoint joinPoint) {
// 获取方法名
String name = joinPoint.getSignature().getName();
// 获取方法的参数
System.out.println(name + "方法的参数是" + Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(value = "execution(public int com.mohanqing.aop.CalImpl.*(..))", returning = "result") // returning = "result" 绑定返回结果
public void afterReturn(JoinPoint joinPoint, Object result) {
String name = joinPoint.getSignature().getName();
System.out.println(name + "方法的结果是" + result);
}
}
更多推荐




所有评论(0)