本文旨在帮助入门和了解aop的概念以及基本用法,如有错误请在评论区指出,万分感谢。
部分资料出自尚硅谷课堂笔记,改内容更好,更完善。
使用aop编程的话,我们需要先导入需要的依赖
二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。
杨超越是一个明星,她会唱歌和跳舞,她现在想要举办一场演唱会,那么需要场地的租用和场地搭建这个环境的准备,已经后续的拆除。此时对于这个演唱会核心的内容就是明星杨超越唱歌,跳舞,那么非核心的内容就是场地的搭建,拆除,租用等等,这时候对杨超越来说,我只会唱歌跳舞,这方面的我不会,所以此时就可以让他的经纪人去找负责对应业务的职员搭建和准备演唱会。那么这个经纪人就属于代理。核心业务是跳舞唱歌,非核心业务就是演唱会的相关筹办。 当我们需要对核心代码增加非核心业务的逻辑时可以采用代理的技术。
静态代理是在编译时期就已经确定的代理方式,在静态代理中,需要手动创建一个代理类,该代理类与被代理类实现相同的接口,并持有一个对被代理对象的引用。通过在代理类中调用被代理对象的方法前后加入自定义的逻辑,实现对目标对象方法的增强或控制。
动态代理是在运行时期根据被代理对象生成代理类的方式。在动态代理中,不需要手动创建代理类,而是通过使用Java的反射机制,在运行时动态地创建代理类和代理对象。动态代理可以代理任何实现了接口的类,它通过一组接口来描述被代理类的行为,并提供了一个InvocationHandler接口的实现类来处理代理对象的所有方法调用。在方法被调用时,代理对象会将方法的调用转发给InvocationHandler的invoke()方法,并可以在此方法中添加额外的逻辑。
它允许开发人员分离横切关注点(cross-cutting concerns)和核心业务逻辑。横切关注点是那些存在于应用程序中多个模块中的功能,例如日志记录、性能统计、安全性和事务管理等。通过 AOP,这些横切关注点可以被模块化地定义,并且可以被动态地应用到整个应用程序中。也就是说将核心代码和非核心代码分割开。
package com.ssmLearn;
/**
* + - * / 运算的标准接口!
*/
public interface Calculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
package com.ssmLearn;
import org.springframework.stereotype.Component;
/**
* 实现计算接口,单纯添加 + - * / 实现! 掺杂其他功能!
*/
//最后必须放到ioc
@Component
public class CalculatorPureImpl implements Calculator {
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
package com.ssmLearn.Aop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//使用注解配置插入的代理目标
@Aspect
@Component
public class AchiveAop {
@Before("execution(* com.ssmLearn.CalculatorPureImpl.*(..))")
public void start(){
System.out.println("这是初始化方法");
}
@After("execution(* com.ssmLearn.CalculatorPureImpl.*(..)))")
public void end(){
System.out.println("这是结束方法");
}
@AfterThrowing(value = "execution(public int com.ssmLearn.CalculatorPureImpl.*(..))")
public void catchExection(){
System.out.println("出现异常");
}
}
package com.ssmLearn.config;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = "com.ssmLearn")
//这个是配置的 aspect代理启动入口
@EnableAspectJAutoProxy
public class javaConfig{
}
import com.ssmLearn.Calculator;
import com.ssmLearn.config.javaConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
//@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
@SpringJUnitConfig(value = {javaConfig.class})
class AopTest {
@Autowired
private Calculator calculator;
@Test
public void testCalculator(){
int res = calculator.add(1,0);
System.out.println("res = " + res);
}
@Test
public void test(){
// 使用配置类 就可以直接使用这个ioc容器 直接使用后AnnotationConfigApplicationContext
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(javaConfig.class);
Calculator bean = applicationContext.getBean(Calculator.class);
int res = bean.add(1,2);
System.out.println("res = " + res);
}
}
实现ioc容器管理需要 创建容器(根据配置类创建)->获取对象(根绝需求获得bean对象)->调用对象的方法(通过指定class文件获取)->关闭容器(避免溢出)