Spring中的IOC和AOP_spring aop和ioc
文章目录
- 一、什么是Spring
- 二、IOC(控制反转)
- 三、AOP(面向切面编程)
-
- 1、什么是AOP?
- 2、AOP的核心概念
- 3、核心概念代码示例
- 4、AOP的实现
- 5、动态代理代码示例
- 6、AOP的应用场景
- 四、总结AOP 和 IOC 结合使用的好处
一、什么是Spring
spring的核心概念:
Spring 框架是一款轻量级的开发框架,核心思想是 IOC(控制反转)和 AOP(面向切面编程)。为 Java 应用程序开发提供组件管理服,用于组件之间的解耦,以及简化第三方JavaEE中间件技术的使用(IMS、任务调度、缓存、ORM 框架),是一个基础架构型的开发框架;。
二、IOC(控制反转)
什么是IOC?
IOC(Inversion of Control,控制反转)是Spring框架的核心思想之一。传统的程序设计中,对象的创建和依赖关系的管理是由程序员手动完成的。而在Spring中,对象的创建和依赖关系的管理交给了Spring容器来处理,这就是所谓的“控制反转”。
1、IOC的实现方式
Spring通过依赖注入(Dependency Injection, DI)来实现IOC。依赖注入是指Spring容器在运行时将对象所依赖的其他对象自动注入到目标对象中,而不需要程序员手动去创建和管理这些依赖关系。
2、代码示例
在Spring中,我们可以通过依赖注入来实现:构造注入或者set注入
// 通过构造函数注入public class IStudentServiceImp implements IStudentService { IStudentDao dao ; public IStudentServiceImp(IStudentDao dao) { this.dao = dao; } public void save() { System.out.println(\"这是service的save方法\"); dao.save(); }}//set注入public class IStudentServiceImp implements IStudentService { IStudentDao dao ; public void setDao(IStudentDao dao) { this.dao = dao; } public void save() { System.out.println(\"这是service的save方法\"); dao.save(); }}
然后在Spring的配置文件中(如applicationContext.xml)进行配置:
<bean id=\"IStudentDaoImp\" class=\"com.apesource.dao.IStudentDaoImp\"></bean> <bean id=\"IStudentServiceImp\" class=\"com.apesource.service.IStudentServiceImp\"> <constructor-arg index=\"0\" ref=\"IStudentDaoImp\"></constructor-arg></bean>
<bean id=\"IStudentDaoImp\" class=\"com.apesource.dao.IStudentDaoImp\"></bean> <bean id=\"IStudentServiceImp\" class=\"com.apesource.service.IStudentServiceImp\"> <property name=\"dao\" ref=\"IStudentDaoImp\"></property> </bean>
3、IOC 的应用场景
1. 依赖注入(DI)
场景: 对象之间的依赖关系由容器动态注入,而不是在代码中硬编码。
示例: 在Spring中,使用@Autowired注解自动注入依赖对象。
2. 模块化开发
场景: 在大型项目中,模块之间的依赖关系复杂,需要解耦。
示例: 将服务层、数据层、控制层分离,通过IOC容器动态组装。
3. 单例模式管理
场景: 需要确保某些对象在应用中只存在一个实例。
示例: 在Spring中,默认的Bean作用域是单例(Singleton)。
4. 配置管理
场景: 将配置信息(如数据库连接、API密钥)从代码中分离,集中管理。
示例: 在Spring中,使用@Value注解注入配置文件中的值。
5. 测试驱动开发(TDD)
场景: 在单元测试中,需要模拟依赖对象。
示例: 使用Mockito等工具创建模拟对象,并通过IOC容器注入到被测试对象中。
6. 事务管理
场景: 在数据库操作中,需要统一管理事务。
示例: 在Spring中,使用@Transactional注解管理事务。
三、AOP(面向切面编程)
1、什么是AOP?
AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它允许开发者将横切关注点(如日志记录、事务管理、安全性等)从业务逻辑中分离出来。通过AOP,开发者可以在不修改原有代码的情况下,为程序动态地添加功能。
2、AOP的核心概念
切面(Aspect):一个模块化的横切关注点,通常是一个类,包含了一些通知和切点。
通知(Advice):在切面的某个特定连接点上执行的动作。常见的通知类型有:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。
切点(Pointcut):定义了在哪些连接点上应用通知。
连接点(Joinpoint):程序执行过程中的某个特定点,如方法调用或异常抛出。
3、核心概念代码示例
这里我们定义了一个工具类Logger模拟AOP的几个通知:
工具类代码
import org.aspectj.lang.ProceedingJoinPoint;public class Logger { public void beforeMethod(){ System.out.println(\"执行方法时的前置通知\"); } public void returnMethod(){ System.out.println(\"执行方法时的返回通知\");// int i = 1/0; } public void exceptionMethod(){ System.out.println(\"执行方法时的异常通知\"); } public void afterMethod(){ System.out.println(\"执行方法时的后置通知\"); } public Object aroundMethod(ProceedingJoinPoint pjp){ Object object = null; try { System.out.println(\"环绕通知的前置通知\"); object = pjp.proceed(pjp.getArgs()); System.out.println(\"环绕通知的返回通知\"); } catch (Throwable e) { e.printStackTrace(); System.out.println(\"环绕通知的异常通知\"); }finally { System.out.println(\"环绕通知的后置通知\"); } return object; }}
配置类文件
<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:aop=\"http://www.springframework.org/schema/aop\" xsi:schemaLocation=\" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd\"> <bean id=\"accountServiceImp\" class=\"com.apesource.service.AccountServiceImp\"></bean> <bean id=\"logger\" class=\"com.apesource.util.Logger\"></bean> <aop:config> <aop:aspect id=\"aopAspect\" ref=\"logger\"> <aop:pointcut id=\"pointCut\" expression=\"execution(* com.apesource.service.*.*(..))\"></aop:pointcut> <!-- --> <!-- --> <!-- --> <!-- --> <aop:around method=\"aroundMethod\" pointcut-ref=\"pointCut\"></aop:around> </aop:aspect> </aop:config></beans>
业务层代码
public interface IAccountService {public void save(int i); public void update(); public void delete(); }public class AccountServiceImp implements IAccountService { public void save(int i) { System.out.println(\"执行service的save方法\"+i); } public void update() { System.out.println(\"执行service的update方法\"); } public void delete() { System.out.println(\"执行service的delete方法\"); }}
测试类代码
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = \"classpath:applicationContext.xml\")public class Test01 { @Autowired public IAccountService service; @Test public void show(){// service.save(1); service.update(); }}
4、AOP的实现
AOP的实现的实现基于动态代理实现,有两种方式:
1、JDK动态代理:基于接口实现,要求目标类必须实现接口。
使用java.lang.reflect.Proxy类创建代理对象。
2、CGLIB动态代理:基于子类实现,不要求目标类实现接口。
使用net.sf.cglib.proxy.Enhancer类创建代理对象。
5、动态代理代码示例
JDK实现:
接口和实现类
public interface ISinger { public void sing();}public class ZhouJieLun implements ISinger { public void sing() { System.out.println(\"===来一首花海===\"); }}
测试类代码
public class Test { public static void main(String[] args) { //被代理对象 final ISinger zJL = new ZhouJieLun(); ISinger proxy = (ISinger) Proxy.newProxyInstance(zJL.getClass().getClassLoader(), zJL.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //增强代码 System.out.println(\"喝完茶在唱歌\"); Object object = method.invoke(zJL,args); return object; } }); proxy.sing(); }}
CGLIB实现
public interface ISinger { public void sing();}public class ZhouJieLun implements ISinger { public void sing() { System.out.println(\"===天青色等烟雨而我在等你===\"); }}
测试类代码
public class Test { public static void main(final String[] args) { //被代理对象 final ISinger zJL = new ZhouJieLun(); ISinger daiLi = (ISinger) Enhancer.create(zJL.getClass(), new InvocationHandler() { public Object invoke(Object o, Method method, Object[] objects) throws Throwable { Object obj = method.invoke(zJL,args); return obj; } }); daiLi.sing(); }
6、AOP的应用场景
1. 日志记录
场景: 在方法执行前后记录日志,便于调试和监控。
示例: 使用AOP在方法执行前后自动记录日志。
2. 权限控制
场景: 在方法执行前进行权限验证。
示例: 使用AOP在方法调用前自动检查用户权限。
3. 性能监控
场景: 监控方法执行时间,识别性能瓶颈。
示例: 使用AOP在方法执行前后记录时间,自动计算执行时长。
4. 缓存管理
场景: 在方法执行前检查缓存,存在则直接返回,避免重复计算。
示例: 使用AOP在方法调用前自动检查缓存。
5. 异常处理
场景: 统一处理系统中的异常,避免重复代码。
示例: 使用AOP在方法抛出异常时自动捕获并处理。
6. 事务管理
场景: 在数据库操作中确保事务的原子性。
示例: 使用AOP在方法执行前后自动管理事务。
四、总结AOP 和 IOC 结合使用的好处
降低代码耦合度,提升模块化。
提升代码复用性,减少重复代码。
简化开发流程,提高开发效率。
增强可维护性,便于修改和调整。
提高系统灵活性,支持动态调整。
统一管理横切关注点,提升代码可读性。
支持声明式编程,简化复杂功能实现。
增强测试能力,提升测试覆盖率。
提升系统性能,优化资源使用。
简化复杂功能实现,降低开发难度。
通过结合使用AOP和IOC,开发者可以更高效地构建灵活、可维护和高性能的应用系统。