Spring從@Aspect到Advisor使用演示實例
演示1 - 代理創(chuàng)建器
public class A17 {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("aspect1", Aspect1.class);
context.registerBean("config", Config.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
// BeanPostProcessor
// 創(chuàng)建 -> (*) 依賴注入 -> 初始化 (*)
context.refresh();
// for (String name : context.getBeanDefinitionNames()) {
// System.out.println(name);
// }
/*
第一個重要方法 findEligibleAdvisors 找到有【資格】的 Advisors
a. 有【資格】的 Advisor 一部分是低級的, 可以由自己編寫, 如下例中的 advisor3
b. 有【資格】的 Advisor 另一部分是高級的, 由本章的主角解析 @Aspect 后獲得
*/
AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
List<Advisor> advisors = creator.findEligibleAdvisors(Target2.class, "target2");
/*for (Advisor advisor : advisors) {
System.out.println(advisor);
}*/
/*
第二個重要方法 wrapIfNecessary
a. 它內(nèi)部調(diào)用 findEligibleAdvisors, 只要返回集合不空, 則表示需要創(chuàng)建代理
*/
Object o1 = creator.wrapIfNecessary(new Target1(), "target1", "target1");
System.out.println(o1.getClass());
Object o2 = creator.wrapIfNecessary(new Target2(), "target2", "target2");
System.out.println(o2.getClass());
((Target1) o1).foo();
/*
學(xué)到了什么
a. 自動代理后處理器 AnnotationAwareAspectJAutoProxyCreator 會幫我們創(chuàng)建代理
b. 通常代理創(chuàng)建的活在原始對象初始化后執(zhí)行, 但碰到循環(huán)依賴會提前至依賴注入之前執(zhí)行
c. 高級的 @Aspect 切面會轉(zhuǎn)換為低級的 Advisor 切面, 理解原理, 大道至簡
*/
}
static class Target1 {
public void foo() {
System.out.println("target1 foo");
}
}
static class Target2 {
public void bar() {
System.out.println("target2 bar");
}
}
@Aspect // 高級切面類
@Order(1)
static class Aspect1 {
@Before("execution(* foo())")
public void before1() {
System.out.println("aspect1 before1...");
}
@Before("execution(* foo())")
public void before2() {
System.out.println("aspect1 before2...");
}
}
@Configuration
static class Config {
/*@Bean // 低級切面
public Advisor advisor3(MethodInterceptor advice3) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* foo())");
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice3);
return advisor;
}
@Bean
public MethodInterceptor advice3() {
return invocation -> {
System.out.println("advice3 before...");
Object result = invocation.proceed();
System.out.println("advice3 after...");
return result;
};
}*/
}
}收獲??
AnnotationAwareAspectJAutoProxyCreator 的作用
- 將高級 @Aspect 切面統(tǒng)一為低級 Advisor 切面
- 在合適的時機創(chuàng)建代理
findEligibleAdvisors 找到有【資格】的 Advisors
- 有【資格】的 Advisor 一部分是低級的, 可以由自己編寫, 如本例 A17 中的 advisor3
- 有【資格】的 Advisor 另一部分是高級的, 由解析 @Aspect 后獲得
wrapIfNecessary
- 它內(nèi)部調(diào)用 findEligibleAdvisors, 只要返回集合不空, 則表示需要創(chuàng)建代理
- 它的調(diào)用時機通常在原始對象初始化后執(zhí)行, 但碰到循環(huán)依賴會提前至依賴注入之前執(zhí)行
演示2 - 代理創(chuàng)建時機
public class A17_1 {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(ConfigurationClassPostProcessor.class);
context.registerBean(Config.class);
context.refresh();
context.close();
// 創(chuàng)建 -> (*) 依賴注入 -> 初始化 (*)
/*
學(xué)到了什么
a. 代理的創(chuàng)建時機
1. 初始化之后 (無循環(huán)依賴時)
2. 實例創(chuàng)建后, 依賴注入前 (有循環(huán)依賴時), 并暫存于二級緩存
b. 依賴注入與初始化不應(yīng)該被增強, 仍應(yīng)被施加于原始對象
*/
}
@Configuration
static class Config {
@Bean // 解析 @Aspect、產(chǎn)生代理
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
return new AnnotationAwareAspectJAutoProxyCreator();
}
@Bean // 解析 @Autowired
public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor() {
return new AutowiredAnnotationBeanPostProcessor();
}
@Bean // 解析 @PostConstruct
public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
return new CommonAnnotationBeanPostProcessor();
}
@Bean
public Advisor advisor(MethodInterceptor advice) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* foo())");
return new DefaultPointcutAdvisor(pointcut, advice);
}
@Bean
public MethodInterceptor advice() {
return (MethodInvocation invocation) -> {
System.out.println("before...");
return invocation.proceed();
};
}
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
static class Bean1 {
public void foo() {
}
public Bean1() {
System.out.println("Bean1()");
}
@Autowired public void setBean2(Bean2 bean2) {
System.out.println("Bean1 setBean2(bean2) class is: " + bean2.getClass());
}
@PostConstruct public void init() {
System.out.println("Bean1 init()");
}
}
static class Bean2 {
public Bean2() {
System.out.println("Bean2()");
}
@Autowired public void setBean1(Bean1 bean1) {
System.out.println("Bean2 setBean1(bean1) class is: " + bean1.getClass());
}
@PostConstruct public void init() {
System.out.println("Bean2 init()");
}
}
}收獲??
代理的創(chuàng)建時機
- 初始化之后 (無循環(huán)依賴時)
- 實例創(chuàng)建后, 依賴注入前 (有循環(huán)依賴時), 并暫存于二級緩存
依賴注入與初始化不應(yīng)該被增強, 仍應(yīng)被施加于原始對象
演示3 - @Before 對應(yīng)的低級通知
public class A17_2 {
static class Aspect {
@Before("execution(* foo())")
public void before1() {
System.out.println("before1");
}
@Before("execution(* foo())")
public void before2() {
System.out.println("before2");
}
public void after() {
System.out.println("after");
}
public void afterReturning() {
System.out.println("afterReturning");
}
public void afterThrowing() {
System.out.println("afterThrowing");
}
public Object around(ProceedingJoinPoint pjp) throws Throwable {
try {
System.out.println("around...before");
return pjp.proceed();
} finally {
System.out.println("around...after");
}
}
}
static class Target {
public void foo() {
System.out.println("target foo");
}
}
@SuppressWarnings("all")
public static void main(String[] args) throws Throwable {
AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new Aspect());
// 高級切面轉(zhuǎn)低級切面類
List<Advisor> list = new ArrayList<>();
for (Method method : Aspect.class.getDeclaredMethods()) {
if (method.isAnnotationPresent(Before.class)) {
// 解析切點
String expression = method.getAnnotation(Before.class).value();
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(expression);
// 通知類
AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice(method, pointcut, factory);
// 切面
Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
list.add(advisor);
}
}
for (Advisor advisor : list) {
System.out.println(advisor);
}
/*
@Before 前置通知會被轉(zhuǎn)換為下面原始的 AspectJMethodBeforeAdvice 形式, 該對象包含了如下信息
a. 通知代碼從哪兒來
b. 切點是什么(這里為啥要切點, 后面解釋)
c. 通知對象如何創(chuàng)建, 本例共用同一個 Aspect 對象
類似的通知還有
1. AspectJAroundAdvice (環(huán)繞通知)
2. AspectJAfterReturningAdvice
3. AspectJAfterThrowingAdvice
4. AspectJAfterAdvice (環(huán)繞通知)
*/
}
}收獲??
@Before 前置通知會被轉(zhuǎn)換為原始的 AspectJMethodBeforeAdvice 形式, 該對象包含了如下信息
- 通知代碼從哪兒來
- 切點是什么(這里為啥要切點, 后面解釋)
- 通知對象如何創(chuàng)建, 本例共用同一個 Aspect 對象
類似的還有
- AspectJAroundAdvice (環(huán)繞通知)
- AspectJAfterReturningAdvice
- AspectJAfterThrowingAdvice (環(huán)繞通知)
- AspectJAfterAdvice (環(huán)繞通知)
到此這篇關(guān)于Spring從@Aspect到Advisor使用演示實例的文章就介紹到這了,更多相關(guān)Spring @Aspect Advisor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java利用InputStream類實現(xiàn)文件讀取與處理
在Java開發(fā)中,輸入流(InputStream)是一個非常重要的概念,它涉及到文件讀寫、網(wǎng)絡(luò)傳輸?shù)榷鄠€方面,InputStream類是Java中輸入流的抽象基類,定義了讀取輸入流數(shù)據(jù)的方法,本文將以InputStream類為切入點,介紹Java中的輸入流概念及其應(yīng)用,需要的朋友可以參考下2023-11-11
SpringBoot指標(biāo)監(jiān)控功能實現(xiàn)
這篇文章主要介紹了SpringBoot指標(biāo)監(jiān)控功能實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06
利用Jacob將Excel轉(zhuǎn)換PDF的問題匯總
項目中經(jīng)常會遇到將excel轉(zhuǎn)換成PDF的需求,下面這篇文章主要給大家介紹了關(guān)于如何利用Jacob將Excel轉(zhuǎn)換PDF問題的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05
springmvc使用JSR-303進(jìn)行數(shù)據(jù)校驗實例
本篇文章主要介紹了詳解springmvc使用JSR-303進(jìn)行數(shù)據(jù)校驗,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02

