AOP是“Aspect Oriented Programming”的缩写,意思是面向切面编程。面向切面的编程是一种新的编程技术,追求的是调用者和被调用者之间的解耦,它弥补了面向对象编程在跨越模块行为上的不足。AOP引进了Aspect概念,它将多个类的重复代码封装到一个可重用模块中,允许程序员把横切关注点模块化,进而消除面向对象编程所引起的代码混乱和分散问题,增强系统的可维护性和代码的可重用性,如安全、事务、日志等横切关注。当系统开发变得越来越庞大时,就可以使用AOP轻松解决横切关注点和调用者和被调用者之间的解耦问题。
AOP是Spring框架的一个关键技术,它和Spring的IoC技术一样重要,虽然AOP进一步完善了Spring的IoC容器,但Spring的IoC容器并不依赖于AOP,这就意味着如果没有必要可以不使用它。主要的功能是:日志记录,性能统计,权限管理,事务处理,异常处理等等。
以上都是摘要于:http://blog.youkuaiyun.com/hanzhou4519/article/details/7704245和http://blog.youkuaiyun.com/wuyueyuljh/article/details/7475132
使用AOP就必须先配置AOP。今天就因为没有配置好AOP而纠结了一天。还好csdn的牛人的心肠好。配置如下,我用的myeclipse8.6,可以通过myeclipse的工具自动导入jar包。选中项目,选MyEclipse ------->project capabilities------>add Spring capabilities..然后选择版本。并把核心库和AOP的库都加进来。就可以省略自己导包了。但是我今天自己导包反而不能出来。所以。还是建议用工具吧。就因为这个,我悲剧了一天呢。
然后就可以在applicationContext.xml中配置了。
<bean id="userdaoImp" class="imp.UserDaoImpl"></bean>
<bean id="aop" class="aop.CreateAop"></bean>
<aop:config>
<!-- 配置切面 -->
<aop:aspect id="ap" ref="aop">
<!-- 配置切入点 :expression={返回任意类型或不返回 ,这个包下的任意类的任意方法和任意参数}-->
<!-- <aop:pointcut expression="execution(* imp.*.*(String))" id="ep"/> 这个String表示只能传一个String的参数,如果不匹配将不执行这个方法-->
<aop:pointcut expression="execution(* imp.*.*(..))" id="ep"/>
<!-- 配置通知 -->
<aop:after method="doAfter" pointcut-ref="ep"/> <!--执行方法之前的动作-->
<aop:before method="doBeofore" pointcut-ref="ep"/><!--执行方法之后的动作-->
<aop:around method="doAround" pointcut-ref="ep"/><!--每个方法都执行的动作,环绕通知-->
<aop:after-throwing method="doException" pointcut-ref="ep" throwing="ex"/><!--抛异常后的通知-->
</aop:aspect>
</aop:config>
然后要写一个切面类:对了这个切面类应该是最写的。这就不做排序了。
public class CreateAop {
//在方法之前执行的动作
public void doBeofore(JoinPoint jointPoint){
System.out.println("--------权限验证");
//获取执行之前的类的信息
System.out.println("方法执行的类:"+jointPoint.getTarget().getClass().getName());
System.out.println("执行的方法:"+jointPoint.getSignature().getName());
System.out.print("执行的参数有:");
Object obj[]=jointPoint.getArgs();
for(int i=0;i<obj.length;i++){
System.out.print(" "+obj[i]+" ");
}
}
//在方法之后执行的动作
public void doAfter(JoinPoint jointPoint1){
System.out.println("--------记录日志");
//获取执行之前的类的信息
StringBuffer sb=new StringBuffer();
sb.append(jointPoint1.getTarget().getClass().getName());
sb.append(".");
sb.append(jointPoint1.getSignature().getName());
sb.append("(");
Object obj[]=jointPoint1.getArgs();
if(obj.length>0){
for(int i=0;i<obj.length-1;i++){
sb.append(obj[i]);
sb.append(",");
}
sb.append(obj[obj.length-1]);
}
sb.append(")");
System.out.println(sb.toString());
}
//环绕通知
public void doAround(ProceedingJoinPoint pjp){
long time=System.currentTimeMillis();
try {
pjp.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long time1=System.currentTimeMillis();
System.out.println("方法执行了"+(time1-time)+"毫秒");
}
//抛出异常通知
public void doException(JoinPoint jointPoint,Exception ex){
if(ex!=null){
this.sendMsg();
}
System.out.println("抛异常了");
}
public void sendMsg(){
System.out.println("老板,抛异常了。。。");
}
}
这里有一个bug就是抛异常后:本想让人执行sendMsg方法。但是就是不执行。。希望能有人够想想告诉我吧。。谢谢了。
这里的两个接口和实现类就不写了。AOP最主要的地方就是配置文件和切面类了。测试的时候:注意;
//XmlBeanFactory不支持AOP
// ClassPathResource cpr=new ClassPathResource("applicationContext.xml");
// XmlBeanFactory factory=new XmlBeanFactory(cpr);
// UserDao userdao=(UserDao)factory.getBean("userdaoImp");
// userdao.insert("young");
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userdao=(UserDao)factory.getBean("userdaoImp");
userdao.insert("young");
System.out.println("************************");
userdao.test();
XmlBeanFactory不支持AOP。今天就先写到这吧。明天继续学习。
使用注解配置AOP:那配置文件中就不用配置AOP了。只需配置aop类和实现类就行了。
@Aspect //配置切面 public class CreateAop implements ThrowsAdvice { @Pointcut("execution(* imp.*.*(..))") //配置切入点 private void apMethod(){} @Before("apMethod()") public void doBeofore(JoinPoint jointPoint){//在方法之前执行的动作 System.out.println("--------权限验证"); //获取执行之前的类的信息 // System.out.println("方法执行的类:"+jointPoint.getTarget().getClass().getName()); // System.out.println("执行的方法:"+jointPoint.getSignature().getName()); // System.out.print("执行的参数有:"); // Object obj[]=jointPoint.getArgs(); // for(int i=0;i<obj.length;i++){ // System.out.print(" "+obj[i]+" "); // } System.out.println("日志记录:(方法执行后)类名:"+jointPoint.getTarget().getClass().getName()+"\t"+"方法名:"+jointPoint.getSignature().getName()+"\t"); System.out.print("参数:"); Object obj[] =jointPoint.getArgs(); for(Object object:obj){ System.out.print(object+" "); } } @After("apMethod()") public void doAfter(JoinPoint jointPoint1){//在方法之后执行的动作 System.out.println("--------记录日志"); //获取执行之前的类的信息 StringBuffer sb=new StringBuffer(); sb.append(jointPoint1.getTarget().getClass().getName()); sb.append("."); sb.append(jointPoint1.getSignature().getName()); sb.append("("); Object obj[]=jointPoint1.getArgs(); if(obj.length>0){ for(int i=0;i<obj.length-1;i++){ sb.append(obj[i]); sb.append(","); } sb.append(obj[obj.length-1]); } sb.append(")"); System.out.println(sb.toString()); } @Around("apMethod()") public void doAround(ProceedingJoinPoint pjp){//环绕通知 long time=System.currentTimeMillis(); try { pjp.proceed(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } long time1=System.currentTimeMillis(); System.out.println("方法执行了"+(time1-time)+"毫秒"); } @AfterThrowing(pointcut=("apMethod()"),throwing="e") public void doThorwing(JoinPoint jointPoint,Throwable e){//抛出异常通知 // System.out.println(e.getMessage()); this.sendMsg(e.getMessage()); } public void sendMsg(String ex){ if(ex!=null){ System.out.println("老板,抛异常了。。。"); } }