目录
1.AOP核心概念
2.AOP入门案例思路分析
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
@Configuration
@ComponentScan("com")
@EnableAspectJAutoProxy //告诉Sping是拿注解开发的AOP
public class SpringConfig {
}
@Component //Spring控制的Bean
@Aspect //告诉Spring这是一个AOP
public class MyAdvice {//通知类
@Pointcut("execution(void com.dao.BookDao.update())")//接口的方法
private void pt(){}//切入点
@Before("pt()")
public void method(){//通知
long l = System.currentTimeMillis();
System.out.println(l);
}
}
public interface BookDao {
public void save();
public void update();
}
@Repository
public class BookDaoImpl implements BookDao{
public void save() {
long l = System.currentTimeMillis();
System.out.println(l);
System.out.println("save...");
}
public void update() {
System.out.println("update...");
}
}
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
bookDao.update();
//1653807198976
//update...
}
}
3.AOP工作流程
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
bookDao.update();
//1653807198976
//update...
System.out.println(bookDao);//com.dao.impl.BookDaoImpl@6f603e89
System.out.println(bookDao.getClass());//class com.sun.proxy.$Proxy19 代理对象
}
}
4.AOP切入点表达式
5.AOP的控制类型
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component //Spring控制的Bean
@Aspect //告诉Spring这是一个AOP
//通知类
public class MyAdvice {
//定义了update()的切入点
@Pointcut("execution(void com.dao.BookDao.update())")
private void pt(){}
//定义了selectId()的切入点
@Pointcut("execution(int com.dao.BookDao.selectId())")
private void pt2(){}
// @Before("pt()")
public void before(){
System.out.println("before...");
}
// @After("pt()")
public void after(){
System.out.println("after...");
}
@Around("pt()")//没有返回值的情况
public void aroundUpdate(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before...");
//对原始方法的调用
pjp.proceed();
System.out.println("around after...");
}
@Around("pt2()")//有返回值的情况
public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before...");
//对原始方法的调用
Object proceed = pjp.proceed();//原始方法的返回值
System.out.println("around after...");
return proceed;//把原始操作的返回值返回去
}
// @AfterReturning("pt2()")
//只有在原有方法运行完没有异常才会运行
public void afterReturning(){
System.out.println("afterReturning...");
}
// @AfterThrowing("pt2()")
//只有在原有方法抛出异常才会运行
public void afterThrowing(){
System.out.println("afterThrowing...");
}
}
环绕通知:测量业务层接口万次执行效率
Signature signature = pjp.getSignature();
String className = signature.getDeclaringTypeName();//类型名
String methodName = signature.getName();//方法名
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class ProjectAdvice {
//匹配业务层的所有方法
@Pointcut("execution(* com.service.*Service.*(..))")
private void ServicePt(){}
@Around("ServicePt()")
public void runSpeed(ProceedingJoinPoint pjp) throws Throwable {
Signature signature = pjp.getSignature();
String className = signature.getDeclaringTypeName();//类型名
String methodName = signature.getName();//方法名
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
pjp.proceed();
}
long end = System.currentTimeMillis();
System.out.println("万次执行"+className+"."+methodName+"----->"+(end-start)+"ms");
}
}
6.AOP通知获取数据
环境
public interface BookDao {
public String save(int id,String password);
}
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
String save = bookDao.save(100,"password");
System.out.println(save);
}
}
6.1获取、修改参数列表
@Component
@Aspect
//1.获取参数列表,所有类型的通知都可以
public class MyAdvice {
//定义了save()的切入点
@Pointcut("execution(* com.dao.BookDao.save(..))")
private void pt(){}
@Before("pt()")
public void before(JoinPoint jp) {
Object[] args = jp.getArgs();//获取参数
System.out.println("before... 参数列表:" + Arrays.toString(args));
}
@After("pt()")
public void after(JoinPoint jp) {
Object[] args = jp.getArgs();//获取参数
System.out.println("after... 参数列表:" + Arrays.toString(args));
}
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before...");
//对原始方法的调用
Object[] args = pjp.getArgs();//获取参数
args[0] = 200;//修改参数
Object proceed = pjp.proceed(args);//传入修改后的参数,执行原有的方法
System.out.println("around after...");
return proceed;//把原始操作的返回值返回去
}
}
6.2 获取返回值
@Component
@Aspect
//2.获取返回值,两个操作能用
public class MyAdvice2 {
//定义了save()的切入点
@Pointcut("execution(* com.dao.BookDao.save(..))")
private void pt() {
}
@AfterReturning(value = "pt()", returning = "ret")
//只有在原有方法运行完没有异常才会运行
public void afterReturning(Object ret) {//如果有JoinPoint pj,这个切入点的参数必须是第一个
//用ret接收返回值
System.out.println("afterReturning..." + ret);
}
}
6.3 获取异常
@Component
@Aspect
//3.获取异常信息,两个操作能用
public class MyAdvice3 {
//定义了save()的切入点
@Pointcut("execution(* com.dao.BookDao.save(..))")
private void pt() {
}
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) {
System.out.println("around before...");
//对原始方法的调用
Object proceed = null;
try {
proceed = pjp.proceed();
} catch (Throwable throwable) {
//拿到异常信息
System.out.println(throwable);
}
System.out.println("around after...");
return proceed;//把原始操作的返回值返回去
}
@AfterThrowing(value = "pt()", throwing = "t")
//只有在原有方法抛出异常才会运行
public void afterThrowing(Throwable t) {
System.out.println("afterThrowing..." + t);
}
}
参数处理:百度网盘密码数据兼容处理
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
@Component
@Aspect
public class ProjectAdvice {
@Pointcut("execution(boolean com.service.ResourcesService.openURL(String,String))")
private void pt() {}
@Around("pt()")
public Object checkPassword(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
for (int i = 0; i < args.length; i++) {
//判断是不是字符串
if (args[i].getClass().equals(String.class)) {
//去空格
args[i] = args[i].toString().trim();
}
}
Object proceed = pjp.proceed(args);
return proceed;
}
}
@Configuration
@ComponentScan("com")
@EnableAspectJAutoProxy
public class SpringConfig {
}
@Repository
public class ResourvesDaoImpl implements ResourcesDao {
public boolean openURL(String url, String password) {
//模拟密码校验
boolean ret = password.equals("root");
return ret;
}
}
@Service
public class ResourcesServiceImpl implements ResourcesService {
@Autowired
private ResourcesDao resourcesDao;
public boolean openURL(String url, String password) {
return resourcesDao.openURL(url, password);
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
ResourcesService resourcesService = context.getBean(ResourcesService.class);
boolean res = resourcesService.openURL("http://pan.baidu.com/haha", "root ");
System.out.println(res);
}
}