Spring的两大核心功能IOC(控制反转)和AOP(面向切面编程)用于项目各层次的解耦及非入侵式开发和简化开发和维护成本,根据需求可用于任何java项目。
目标:使用Spring的面向切面编程AOP(Aspect Oriented Programming).
备注:个人理解,切面表现在编程里就是针对对象方法的拦截,如方法执行前或执行后执行一段代码。面向对象中对象是一个整体,切面则是横向思考的一种方式。
准备工作:
1.下载spring
下载后的压缩包为spring-3.2.0.M2-dist.zip,为spring3.2版本.
2.下载commons-logging.jar文件,spring依赖这个jar,否则运行异常,用于日志输出 下载地址:地址:http://commons.apache.org/logging/download_logging.cgi。
3.aspectj.jar aspectjweaver.jar aopalliance.jar,是切面开发需要的包。我下到的是aspectj-1.6.10.jar,aspectjweaver-1.5.3.jar,aopalliance.jar
4.cglib-nodep.jar ,cglib用于无实现接口对象的代理对象生成。我下到的是cglib-nodep-2.1_3.jar
工程搭建:
一、新建一个 Java Project
二、导入jar包
经过测试spring运行ioc最少导入以下4个包:
spring-core-3.2.0.M2.jar
spring-context-3.2.0.M2.jar
spring-beans-3.2.0.M2.jar
spring-expression-3.2.0.M2.jar
spring-aop-3.2.0.M2.jar
然后导入
commons-logging-1.1.1.jar
aspectj-1.6.10.jar,aspectjweaver-1.5.3.jar,aopalliance.jar
cglib-nodep-2.1_3.jar
好了,环境搭好了,然后就是新建类并在xml中描述该类的实例化方式。
这里使用applicationContext.xml描述.
相关描述说明看文档spring-3.2.0.M2/docs/reference/html/beans.html
代码:
applicationContext.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- 包扫描,注册了各种处理器,包括Controller Service Component注解等的处理器 --> <context:component-scan base-package="com.zk.*"/> <!-- aop自动代理配置,配置后直接使用注解 --> <aop:aspectj-autoproxy/> </beans>
StudentAction.java
package com.zk.action; import org.aspectj.lang.annotation.AfterReturning; import org.springframework.stereotype.Controller; @Controller public class StudentAction { private String name="zhangsan"; public String getName(){ System.out.println("StudentAction getName()执行了"); return name; } public void setName(String name){ this.name=name; System.out.println("StudentAction setName()执行了2"); //如果抛出异常,则@AfterReturning后置通知将不执行。 //前置通知,最终通知,异常通知将执行,并抛出异常 //throw new RuntimeException(); } }
StudentActionAOP.java
package com.zk.aop; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component @Aspect public class StudentActionAOP { @Before("execution(* com.zk.action.*.*(..))") public void beforeInvoke(){ System.out.println("aop 拦截 ,前置通知");//目标对象的方法执行前执行 } @AfterReturning("execution(* com.zk.action.*.*(..))") public void afterInvoke(){ System.out.println("aop 拦截 ,后置通知");//目标对象的方法正常执行后执行 } @After("execution(* com.zk.action.*.*(..))") public void afterReturnInvoke(){ System.out.println("aop 拦截 ,最终通知");//目标对象的方法无论正常还是异常都执行,即try{}catch(){}finally{}中finally代码段 } @AfterThrowing("execution(* com.zk.action.*.*(..))") public void exceptionInvoke(){ System.out.println("aop 拦截 ,异常通知");//目标对象的方法抛出异常将执行 } }
Main.java
package com.zk.main; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.zk.action.StudentAction; public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); StudentAction studentAction = (StudentAction)ctx.getBean("studentAction"); studentAction.setName("lisi"); } }
运行结果:
aop 拦截 ,前置通知
StudentAction setName()执行了2
aop 拦截 ,最终通知
aop 拦截 ,后置通知
=============================================
使用切面表达式定义切面
package com.zk.aop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class StudentActionAOP {
@Pointcut("execution(* com.zk.action.*.*(..))")//切面定义表达式
public void myPointCut(){}//切面名称 myPointCut()
//--------------
//定义一个Pointcut,然后将各个通知应用到某个切面上,切面可以使用多个
//--------------
@Before("myPointCut()")
public void beforeInvoke(){
System.out.println("aop 拦截 ,前置通知");//目标对象的方法执行前执行
}
@AfterReturning(pointcut="myPointCut()",returning="retVal")
public void afterInvoke(Object retVal){
System.out.println("aop 拦截 ,后置通知"+";retVal="+retVal);//目标对象的方法正常执行后执行
}
@After("myPointCut()")
public void afterReturnInvoke(){
System.out.println("aop 拦截 ,最终通知");//目标对象的方法无论正常还是异常都执行,即try{}catch(){}finally{}中finally代码段
}
@AfterThrowing(pointcut="execution(* com.zk.action.StudentAction.*(..))")
public void exceptionInvoke(){
System.out.println("aop 拦截 ,异常通知");//目标对象的方法抛出异常将执行
}
}
输出结果:
aop 拦截 ,前置通知
StudentAction setName()执行了2
aop 拦截 ,最终通知
aop 拦截 ,后置通知;retVal=null
如果出现 error at ::0 can't find referenced pointcut allAllMethod1 错误,则是aspectjweaver.jar包错误。
换个jar包就可以正确解析表达式了。我这里使用的是 aspectjweaver-1.7.1.jar
aspectjweaver.jar下载 --> http://search.maven.org/ 搜索 aspectjweaver 选择下载1.7.1的jar包就可以了。
!临时找jar包去哪里找呢?
上maven中央仓库搜索! 这是地址:http://search.maven.org/