一.简介
- 通过xml配置,配置目标类和切面类,
<aop:config>
标签将目标类和切面类融合 - 可以将控制层,业务层和数据库访问层都看成一个切面,做统一的异常处理
二.配置文件的各种通知
- pointcut-ref是切入点指向,用来指明切面类各种通知配置到目标类的哪个目标方法中
- 前置通知(aop:before):在目标方法执行前执行
配置文件:<aop:before method="begin" pointcut-ref="point"/>
应用:可以对方法的参数来做校验 - 后置通知(aop:after-returning):目标方法执行后执行
配置文件:<aop:after-returning method="commit" pointcut-ref="point"/>
应用:可以修改方法的返回值
目标方法有返回值可以通过配置后置通知的retuerning属性拿到返回值
returning属性,将目标类返回值存在ret,切面类中可以通过给后置通知传Object ret获得返回的值
如果目标方法有异常,后置通知不会执行 - 异常通知(aop:after-throwing):目标方法出错时执行
配置文件:<aop:after-throwing method="ex" pointcut-ref="point" thorwing="xx"/>
应用:包装异常的信息
异常内容会保存到xx里面
配置异常通知的thorwing="xx"是切面类异常方法ex里面的参数Throwable xx - 最终通知(aop:after):不管什么时候都会执行
配置文件:<aop:after method="finall" pointcut-ref="point"/>
应用:释放资源
如果目标方法有异常,最终通知也会执行 - 环绕通知(aop:around):目标方法执行前后执行的方法,和前置后置通知重复,选择一个写即可
配置文件:<aop:around method="around" pointcut-ref="point"/>
环绕通知需要对目标方法进行放行
三.代码
1.目标类接口
package com.jp.aop;
import com.jp.domain.Person;
public interface PersonDao {
void save(Person person);
//int save(Person person);
}
2.目标类
package com.jp.aop;
import com.jp.domain.Person;
public class PersonDaoImpl implements PersonDao{
@Override
public void save(Person person) {
//int i=1/0;//异常,会被捕捉报错
System.out.println("保存Person成功...");
}
/*@Override
public int save(Person person) {
System.out.println("保存Person成功...");
return 1;
}*/
}
3.切面类
package com.jp.transcation;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyTranscation {
public void begin(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
/*public void commit(Object ret){
System.out.println(ret);
System.out.println("提交事务");
}*/
public void ex(Throwable xx){
System.out.println(xx.getMessage());
System.out.println("有异常了");
}
public void finall(){
System.out.println("最终通知");
}
public void around(ProceedingJoinPoint p) throws Throwable{
System.out.println("环绕通知前");
//放行,执行目标方法
p.proceed();
System.out.println("环绕通知后");
}
}
package com.jp.transcation;
public class Logger {
public void log(){
System.out.println("日志记录。。。");
}
}
package com.jp.transcation;
public class Security {
public void safe(){
System.out.println("安全校验。。。");
}
}
4.配置文件
applicationContext.xml要放在src下
execution切入点表达式
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 目标类 -->
<bean id="personDao" class="com.jp.aop.PersonDaoImpl"></bean>
<!-- MyTranscation切面 -->
<bean id="m" class="com.jp.transcation.MyTranscation"></bean>
<!-- Logger切面 -->
<bean id="log" class="com.jp.transcation.Logger"></bean>
<!-- Security切面 -->
<bean id="security" class="com.jp.transcation.Security"></bean>
<!-- aop配置 -->
<!-- pointcut-ref是切入点指向,用来指明切面类各种通知配置到目标类的哪个目标方法中 -->
<aop:config>
<!-- 切入点表达式配置,可以配置多个切面 -->
<!-- expression="execution (com.jp.aop.PersonDaoImpl.*(..))"代表找到PersonDaoImpl类下任意方法 -->
<aop:pointcut expression="execution (* com.jp.aop.PersonDaoImpl.*(..))" id="point"/>
<!-- 切面配置,指配置切面类m的各种通知到目标类的目标方法中 -->
<aop:aspect ref="m">
<!-- 前置通知 -->
<!-- <aop:before method="begin" pointcut-ref="point"/> -->
<!-- 后置通知 -->
<!-- <aop:after-returning method="commit" pointcut-ref="point"/> -->
<!-- 异常通知 -->
<!-- <aop:after-throwing method="ex" pointcut-ref="point" thorwing="xx"/> -->
<!-- 最终通知 -->
<!-- <aop:after method="finall" pointcut-ref="point"/> -->
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="point"/>
</aop:aspect>
<!-- Logger切面配置 -->
<aop:aspect ref="log">
<aop:pointcut expression="execution (* com.jp.aop..*.*(..))" id="point2"/>
<aop:before method="log" pointcut-ref="point2"/>
</aop:aspect>
<!-- Security切面配置 -->
<aop:aspect ref="security">
<!-- 代表PersonDaoImpl类下以s开头的方法 -->
<aop:pointcut expression="execution (* com.jp.aop.PersonDaoImpl.s*(..))" id="point3"/>
<aop:after method="safe" pointcut-ref="point3"/>
</aop:aspect>
</aop:config>
</beans>
5.测试类
package com.jp.aop;
import java.lang.reflect.Method;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jp.domain.Person;
public class SpringXmlTest {
@Test
public void test1(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
PersonDao personDao = (PersonDao)ac.getBean("personDao");
Person person=new Person();
personDao.save(person);
}
@Test
public void test2(){
Object o=new Object();
Class class1=o.getClass();
Method[] methods = class1.getMethods();
for(Method m:methods){
System.out.println(m);
}
}
}