AOP中的概念
Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面横切性关注点的抽象.
joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)
Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义.
Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知
Target(目标对象):代理的目标对象
Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入.
Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {// 环绕通知
PersonServiceBean bean = (PersonServiceBean) this.targetObject;
Object result = null;
if (bean.getUser() != null) {
// ....advice()-->前置通知
try {
result = method.invoke(targetObject, args);
// afteradvice()-->后置通知
} catch (RuntimeException e) {
// exceptionadvice()-->例外通知
} finally {
// finallyadvice();-->最终通知
}
}
return result;
}
注解方式--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
接口 PersonService.java
package com.dwt1220;
public interface PersonService {
public abstract void save(String name);
public abstract String getPersonName(Integer id);
public abstract void update(String name,Integer id);
}
PersonServiceBean.java
package com.dwt1220;
public class PersonServiceBean implements PersonService {
public String getPersonName(Integer id){
System.out.println("我是getPersonName()方法");
return "xxxx";
}
public void save(String name) {
//throw new RuntimeException("例外");
System.out.println("personService的save()方法");
}
public void update(String name,Integer id){
System.out.println("我是update()fangf");
}
}
MyInterceptor.java
package com.dwt1220;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect//注释,说明此类是AOP,提交给spring管理
public class MyInterceptor {
@Pointcut("execution (* com.dwt1220.PersonServiceBean.*(..))")
private void anyMethod(){};//声明一个切入点
/***********获得参数值(此时拦截方法,只针对有String name参数的方法)****************/
@Before("anyMethod() && args(name)")//
public void doAccessCheck(String name){
System.out.println("前置通知:"+name);
}
/***********获得返回值****************/
@AfterReturning(pointcut="anyMethod()",returning="result")//获得返回值
public void doAfterReturning(String result){
System.out.println("后置通知:"+result);
}
@After("anyMethod()")
public void doAfter(){
System.out.println("最终通知");
}
/***********获得错误****************/
@AfterThrowing(pointcut="anyMethod()",throwing="ex")//获得错误
public void doAfterThrowing(Exception ex){
System.out.println("例外通知:"+ex);
}
/*************环绕通知 返回值 和 参数类型 不可变******************************/
@Around("anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
//if(){//判断用户是否有权限
System.out.println("进入方法");
Object result=pjp.proceed();
System.out.println("退出方法");
//}
return result;
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- 启动对@AspectJ注解的支持 -->
<aop:aspectj-autoproxy/>
<bean id="myInterceptor" class="com.dwt1220.MyInterceptor"/>
<bean id="personService" class="com.dwt1220.PersonServiceBean"/>
</beans>
package com.dwt1220;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService = (PersonService) ctx
.getBean("personService");
System.out.println("拦截save方法,并获得输入参数(或错误信息)----------");
/**********拦截save方法,并获得输入参数(或错误信息)**********************/
personService.save("123");
System.out.println();
System.out.println("拦截getPersonName方法并获得返回参数");
/**********拦截getPersonName方法并获得返回参数**********************/
personService.getPersonName(123);
}
}
XML配置方式声明切面--------------------------------------------------------------------------------------------------------------------------
beans.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="personService" class="com.dwt1220.PersonServiceBean"/>
<bean id="myInterceptor" class="com.dwt1220.MyInterceptor"/>
<aop:config>
<aop:aspect id="myaop" ref="myInterceptor">
<aop:pointcut id="mycut" expression="execution (* com.dwt1220.PersonServiceBean.*(..))" />
<aop:before pointcut-ref="mycut" method="doAccessCheck" />
<aop:after-returning pointcut-ref="mycut" method="doAfterReturning"/>
<aop:after-throwing pointcut-ref="mycut" method="doAfterThrowing" />
<aop:after pointcut-ref="mycut" method="doAfter"/>
<aop:around pointcut-ref="mycut" method="doBasicProfiling" />
</aop:aspect>
</aop:config>
</beans>
MyInterceptor.java
package com.dwt1220;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyInterceptor {
public void doAccessCheck(){
System.out.println("前置通知:");
}
public void doAfterReturning(){
System.out.println("后置通知:");
}
public void doAfter(){
System.out.println("最终通知");
}
public void doAfterThrowing(){
System.out.println("例外通知:");
}
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
//if(){//判断用户是否有权限
System.out.println("进入方法");
Object result=pjp.proceed();
System.out.println("退出方法");
//}
return result;
}
}
execution (* com.dwt1220.PersonServiceBean.*(..))
返回类型 要写包名+类名,
要拦截的类 com.dwt1220.. --com.dwt1220 下的所有类。及其子包下的所有类
方法的参数 要写包名+类名
execution (java.lang.String com.dwt1220..*.*(java.lang.String,..))
execution (!void com.dwt1220.PersonServiceBean.*(..)) ----拦截PersonServiceBean类下所有,有返回值的方法