SpringAOP 面向切面编程(Aspect Oriented Programming)
aop效果:
项目demo:
代码:
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AppConfig {
@Pointcut("execution(* com.spring.demo.service.*.*(..))")
public void businessService() {}
@Before(value = "businessService()")
public void doBefore() {
System.out.println("----------------- doBefore -----------------");
}
@AfterReturning(value = "businessService()")
public void doAfterReturning() {
System.out.println("----------------- doAfterReturning -----------------");
}
@After(value = "businessService()")
public void doAfter() {
System.out.println("----------------- doAfter -----------------");
}
}
import com.spring.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description:
* @author: yz
* @create: 2019/5/27 15:33
*/
@RestController
public class TestController {
@Autowired
UserService userService;
@RequestMapping("/test")
public String test(){
return userService.query();
}
}
public interface UserService {
String query();
}
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public String query() {
System.out.println("------------ yz ------------");
return "------------ yz ------------";
}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
请求url:http://localhost:8080/test
源码调试,编写main方法,使用注解方式:
import com.spring.demo.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
/**
* @description:
* @author: yz
* @create: 2019/5/27 15:23
*/
@ComponentScan("com.spring.demo")
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main.class);
UserService userService = applicationContext.getBean(UserService.class);
// UserService userService = (UserService) applicationContext.getBean("userService");
userService.query();
}
}
断点发现,拿到的service对象已经是被Aop CGLIB代理过的对象,main方法打印aop代理service后的信息:
被代理时间可能发生在第一步,也可能发生在第二步,此时假设发生在第二步,断点打在getBean进行跟踪:
发现singletonObjects 是个map
既然singletonObjects有get,那么就有put,此时切入点查找this.singletonObjects.put
用2分查找法排查jvm运行栈,具体在哪一个方法userService被aop代理。
注意:此时还没有执行到UserService userService = applicationContext.getBean(UserService.class);
也就是说spring aop创建代理代理对象是在第一步执行的:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main.class);
我们将断点打在doGetBean的getSingleton方法,加条件断点,这是个Lambda表达式
重新运行,进入getSingleton方法
至此Spring Aop源码调试完毕。
Spring Aop官网资料:
https://docs.spring.io/spring/docs/5.2.0.BUILD-SNAPSHOT/spring-framework-reference/core.html#aop
其他资料:https://blog.csdn.net/u010890358/article/details/80640433