Spring研究之AOP初试
发布日期:2021-06-30 16:15:38 浏览次数:2 分类:技术文章

本文共 5955 字,大约阅读时间需要 19 分钟。

1、定义业务类接口

1
2
3
4
5
6
7
package 
spring;
 
public 
interface 
IStudent {
  
 
void 
addStudent(String name);
 
}

2、业务实现类

1
2
3
4
5
6
7
8
9
10
package 
spring;
 
public 
class 
StudentServiceImpl 
implements 
IStudent{
     
     
    
public 
void 
addStudent(String name){
         
        
System.out.println(
"add student operation name is"
+name);
    
}
}

3、前置通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package 
spring;
 
import 
java.lang.reflect.Method;
 
import 
org.springframework.aop.MethodBeforeAdvice;
 
public 
class 
BeforeAdvice 
implements 
MethodBeforeAdvice{
 
    
public 
void 
before(Method arg0, Object[] arg1, Object arg2)
            
throws 
Throwable {
        
// TODO Auto-generated method stub
        
System.out.println(
"this is before method"
);
    
}
 
}

4、后置通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package 
spring;
 
import 
java.lang.reflect.Method;
 
import 
org.springframework.aop.AfterReturningAdvice;
 
public 
class 
AfterAdvice 
implements 
AfterReturningAdvice {
 
    
public 
void 
afterReturning(Object arg0, Method arg1, Object[] arg2,
            
Object arg3) 
throws 
Throwable {
        
// TODO Auto-generated method stub
        
System.out.println(
"this is afterreturn method"
);
    
}
 
}

5、环绕通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package 
spring;
 
import 
org.aopalliance.intercept.MethodInterceptor;
import 
org.aopalliance.intercept.MethodInvocation;
 
public 
class 
CompareInterceptor 
implements 
MethodInterceptor{
 
    
public 
Object invoke(MethodInvocation arg0) 
throws 
Throwable {
        
// TODO Auto-generated method stub
        
Object result=
null
;
        
String name=arg0.getArguments()[
0
].toString();
        
if 
(name!=
null
&&name.equalsIgnoreCase(
"kerry"
)) {
            
result=arg0.proceed();
        
}
        
else 
{
            
System.out.println(
"it is not kerry ,not permitted to join!"
);
        
}
        
return 
result;
    
}
 
}

6、配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version=
"1.0" 
encoding=
"UTF-8"
?>
<!DOCTYPE beans PUBLIC 
"-//SPRING//DTD BEAN//EN" 
"http://www.springframework.org/dtd/spring-beans.dtd"
>
 
 
<beans>
  
 
<bean id=
"beforeAdvice" 
class
=
"spring.BeforeAdvice"
></bean>
 
<bean id=
"afterAdvice" 
class
=
"spring.AfterAdvice"
></bean>
 
<bean id=
"compareInterceptor" 
class
=
"spring.CompareInterceptor"
></bean>
 
<bean id=
"studenttarget" 
class
=
"spring.StudentServiceImpl"
></bean>
 
<bean id=
"student" 
class
=
"org.springframework.aop.framework.ProxyFactoryBean"
>
    
<!--代理类的接口-->
  
<property name=
"proxyInterfaces"
>
   
<value>spring.IStudent</value>
  
</property>
    
<!--拦截器-->
  
<property name=
"interceptorNames"
>
    
<list>
     
<value>beforeAdvice</value>
     
<value>afterAdvice</value>
    
<value>compareInterceptor</value>  
    
</list>
  
</property>
    
<!--业务实现类,逻辑代码-->
  
<property name=
"target"
>
    
<ref bean=
"studenttarget"
/>
  
</property>
</bean>
</beans>

7、测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package 
spring;
 
import 
org.springframework.context.ApplicationContext;
import 
org.springframework.context.support.FileSystemXmlApplicationContext;
 
public 
class 
TestAOP {
     
     
    
public 
static 
void 
main(String[] args) {
        
ApplicationContext applicationContext=
new 
FileSystemXmlApplicationContext(
"src//spring/applicationContext.xml"
);
        
IStudent student=(IStudent) applicationContext.getBean(
"student"
);
        
student.addStudent(
"kerry"
);
    
}
}

AOP分析:

1、AOP总体利用动态代理机制实现

2、<bean id="student" class="org.springframework.aop.framework.ProxyFactoryBean">定义代理类,代理类必须知道被代理类的信息,所以配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<bean id=
"student" 
class
=
"org.springframework.aop.framework.ProxyFactoryBean"
>
 
<!--被代理类的接口-->
  
<property name=
"proxyInterfaces"
>
   
<value>spring.IStudent</value>
  
</property>
 
<!--拦截器-->
  
<property name=
"interceptorNames"
>
    
<list>
     
<value>beforeAdvice</value>
     
<value>afterAdvice</value>
    
<value>compareInterceptor</value>  
    
</list>
  
</property>
 
<!--业务实现类,逻辑代码-->
  
<property name=
"target"
>
    
<ref bean=
"studenttarget"
/>
  
</property>

 其中,属性的名称不可修改,对应ProxyFactoryBean的成员变量,以便在获取bean时,知道bean的接口(IStudent student=(IStudent) applicationContext.getBean("student"););如下源代码所示:

1
2
3
4
5
6
7
8
9
10
11
12
/*     */   
public 
static 
final 
String GLOBAL_SUFFIX = 
"*"
;
/*     */   
protected 
final 
Log logger;
/*     */   
private 
String[] interceptorNames;
/*     */   
private 
String targetName;
/*     */   
private 
boolean 
autodetectInterfaces;
/*     */   
private 
boolean 
singleton;
/*     */   
private 
AdvisorAdapterRegistry advisorAdapterRegistry;
/*     */   
private 
boolean 
freezeProxy;
/*     */   
private 
transient 
ClassLoader beanClassLoader;
/*     */   
private 
transient 
BeanFactory beanFactory;
/*     */   
private 
boolean 
advisorChainInitialized;
/*     */   
private 
Object singletonInstance;

3、配置拦截器后,spring首先会检测该名称的bean是否被定义,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
*     */   
private 
void 
checkInterceptorNames()
/*     */   
{
/* 363 */     
if 
(!(ObjectUtils.isEmpty(
this
.interceptorNames))) {
/* 364 */       
String finalName = 
this
.interceptorNames[(
this
.interceptorNames.length - 
1
)];
/* 365 */       
if 
((
this
.targetName != 
null
) || (
this
.targetSource != EMPTY_TARGET_SOURCE) || 
/* 368 */         
(finalName.endsWith(
"*"
)) || (isNamedBeanAnAdvisorOrAdvice(finalName)))
/*     */         
return
;
/* 370 */       
this
.targetName = finalName;
/* 371 */       
if 
(
this
.logger.isDebugEnabled()) {
/* 372 */         
this
.logger.debug(
"Bean with name '" 
+ finalName + 
"' concluding interceptor chain " 
"is not an advisor class: treating it as a target or TargetSource"
);
/*     */       
}
/*     */ 
/* 375 */       
String[] newNames = 
new 
String[
this
.interceptorNames.length - 
1
];
/* 376 */       
System.arraycopy(
this
.interceptorNames, 
0
, newNames, 
0
, newNames.length);
/* 377 */       
this
.interceptorNames = newNames;
/*     */     
}
/*     */   
}

4、通知最后被存储在List容器中

1
2
3
4
5
6
7
8
9
10
11
12
/*     */ 
public 
class 
AdvisedSupport 
extends 
ProxyConfig
/*     */   
implements 
Advised
/*     */ 
{
/*     */   
private 
static 
final 
long 
serialVersionUID = 2651364800145442165L;
/*  70 */   
public 
static 
final 
TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
/*     */   
TargetSource targetSource;
/*     */   
private 
boolean 
preFiltered;
/*     */   
AdvisorChainFactory advisorChainFactory;
/*     */   
private 
transient 
Map methodCache;
/*     */   
private 
List interfaces;
/*     */   
<span style=
"color:#ff0000;"
>
private 
List advisors;
</span>
/*     */   
private 
Advisor[] advisorArray;

5、测试类中的student对象为代理对象,如图所示

转载地址:https://kerry.blog.csdn.net/article/details/42705517 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Hibernate 缓存机制
下一篇:AOP原理

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年05月02日 22时37分51秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章