使用aop的专用标签来完成相关的配置.(AOP标签库)
其中主要表现是使用AspectJ的expression的操作:
execution(modifiers-pattern ret-type-pattern
declaring-type-pattern name-pattern(param-pattern)
throws-pattern)除了返回类型模式,名字模式和参数模式以外,
所有的部分都是可选的。 返回类型模式决定了方法的返回类型必须依次
匹配一个连接点。 你会使用的最频繁的返回类型模式是 *,它代表了匹
配任意的返回类型。 一个全称限定的类型名将只会匹配返回给定类型的方
法。名字模式匹配的是方法名。 你可以使用 * 通配符作为所有或者部分
命名模式。 参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方
法, 而 (..) 匹配了一个接受任意数量参数的方法(零或者更多)。
模式 (*) 匹配了一个接受一个任何类型的参数的方法。 模式
(*,String) 匹配了一个接受两个参数的方法,第一个可以是任
意类型,第二个则必须是String类型
注意在使用之前需要在xml文件的beans标签中加入新的schame文件:并在Eclipse中进行关联配置
下面给出一些常见切入点表达式的例子。
1)任意包下的任意类中的公共方法的执行:
execution(public * *(..))
2)任何一个以“set”开始的方法的执行:
execution(* set*(..))
3)AccountService 接口的任意方法的执行:
execution(* com.briup.service.AccountService.*(..))
4)定义在service包里的任意方法的执行:
execution(* com.briup.service.*.*(..))
5)定义在service包或者子包里的任意方法的执行:
execution(* com.briup.service..*.*(..))
execution(* com.briup.service..*.*(..)) or execution(* com.briup.dao..*.*(..))
注意:
1.从spring容器中拿代理对象的时候也是要用目标对象的名字来拿。
2.没有实现任何接口的目标对象也能产生代理对象。
注意:
例:
1.配置文件xml
2.测试类:
package com.briup.aop.spring.aopConfig;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.briup.pojo.BookService;
import com.briup.pojo.ProductService;
public class aopConfigTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext(
"com/briup/aop/spring/aopConfig/aopConfig.xml");
BookService bs=
cp.getBean("target",BookService.class);
bs.saveBook(1, "lisi");
bs.list();
ProductService ps=
cp.getBean("target1",ProductService.class);
ps.saveProduct(1, "lisi");
ps.getProduct();
}
}
※ 自定义通知类(自定义方法)
需要:aspectjweaver.jar包
在一个切面类中定个多个方法,根据xml文件的配置每个方法都可以织入到切入点的
不同位置,并且advice是在aop的标签中进行配置,不需要再写对应的advice类了
例如:
//这个类相当于我们之前的切面类
//只不过这个切面类中有很多方法都可以织入到切入点上面
//我们可以控制把这里的任何一个方法织入到任何一个切入点上面
public class XmlHandler {
public void beforeTest(JoinPoint p){
System.out.println(p.getSignature().getName()+" before...");
}
public void afterTest(JoinPoint p){
System.out.println(p.getSignature().getName()+" after...");
}
public void afterReturningTest(JoinPoint p){
System.out.println(p.getSignature().getName()+" afterReturning");
}
//在和aroundAdvice结合的时候,这个方法一定要加上这个ProceedingJoinPoint类型的参数
public Object aroundTest(ProceedingJoinPoint pjp)throws Throwable{
//JoinPoint对象不能调用连接点所表示的方法
//ProceedingJoinPoint能调用连接点所表示的方法 pjp.proceed()
System.out.println(pjp.getSignature().getName()+" is start..");
//调用到连接点方法
Object obj = pjp.proceed();
System.out.println(pjp.getSignature().getName()+" is end..");
return obj;
}
public void throwingTest(JoinPoint p,Exception ex){
System.out.println(p.getSignature().getName()+" is throwing..."+ex.getMessage());
}
}
xml文件配置:
注意:
例:
1.自定义通知类
package com.briup.aop.spring.defineAopConfig;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/*
* 自定义通知类(自定义的方法)
*/
public class DefineNoticeAdvice {
/*
* 前置通知,
* 参数必须是joinpoint
*
*/
public void beforeTest(JoinPoint point){
System.out.println("before......");
}
/*
* 后置通知
*/
public void after(JoinPoint point){
//获取方法的镜像
// System.out.println(point.getSignature());
// //获取方法镜像的名字
// System.out.println(
// point.getSignature().getName());
//获取目标对象方法执行的参数
// System.out.println(
// Arrays.toString(point.getArgs()));
//获取目标对象
// System.out.println(point.getTarget());
// System.out.println(point.getThis());
System.out.println("after....");
}
public void afterReturn(JoinPoint point){
System.out.println("after1.....");
}
public Object
around(ProceedingJoinPoint point){
// System.out.println(point.getTarget());
// System.out.println(point.getThis());
// System.out.println(point.getSignature());
// System.out.println(point.getArgs());
Object obj=null;
try {
System.out.println("before.....");
//执行目标对象中的方法
obj=point.proceed();
System.out.println("after....");
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
/*
* 异常通知的方法
* 第一个参数joinPoint
* 第二个参数异常类
*/
public void
throwE(JoinPoint point,Exception ex){
System.out.println(
"exception..."+ex.getMessage());
}
}
2.配置文件xml
3. 测试类:
package com.briup.aop.spring.defineAopConfig;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.briup.pojo.BookService;
import com.briup.pojo.ProductService;
public class defineNoticeaopConfigTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext(
"com/briup/aop/spring/defineAopConfig/defineaopconfig.xml");
BookService bs=
cp.getBean("target",BookService.class);
bs.saveBook(1, "lisi");
bs.list();
// ProductService ps=
// cp.getBean("target1",ProductService.class);
// ps.saveProduct(1, "lisi");
// ps.getProduct();
}
}
※ 使用注解配置AOP:其实就是在上面的类XmlHandler中加入上注解,然后去掉xml中的aop标签配置,这里把类改名为AnnotationHandler,
例子:
@Component
@Aspect
public class AnnotationHandler {
/*
* 在一个方法上面加上注解来定义切入点
* 这个切入点的名字就是这个方法的名字
* 这个方法本身不需要有什么作用
* 这个方法的意义就是:给这个 @Pointcut注解一个可以书写的地方
* 因为注解只能写在方法、属性、类的上面,并且方法名作为切入点的名字
* */
@Pointcut("execution(public * com.briup.aop.service..*.*(..))")
public void myPointCut(){}
//注:这里面的所有方法的JoinPoint类型参数都可以去掉不写,如果确实用不上的话
@Before("myPointCut()")
public void beforeTest(JoinPoint p){
System.out.println(p.getSignature().getName()+" before...");
}
/*
* @After和@AfterReturning
*
* @After标注的方法会在切入点上的方法结束后被调用(不管是不是正常的结束).
* @AfterReturning标注的方法只会在切入点上的方法正常结束后才被调用.
* */
@After("myPointCut()")
public void afterTest(JoinPoint p){
System.out.println(p.getSignature().getName()+" after...");
}
@AfterReturning("myPointCut()")
public void afterReturningTest(JoinPoint p){
System.out.println(p.getSignature().getName()+" afterReturning");
}
@Around("myPointCut()")
public Object aroundTest(ProceedingJoinPoint pjp)throws Throwable{
System.out.println(pjp.getSignature().getName()+" is start..");
//调用连接点的方法去执行
Object obj = pjp.proceed();
System.out.println(pjp.getSignature().getName()+" is end..");
return obj;
}
//在切入点中的方法执行期间抛出异常的时候,会调用这个 @AfterThrowing注解所标注的方法
@AfterThrowing(value="myPointCut()",throwing="ex")
public void throwingTest(JoinPoint p,Exception ex){
System.out.println(p.getSignature().getName()+" is throwing..."+ex.getMessage());
}
}
xml配置:注意给例子中使用的其他的类上面也使用注解
注意:
例:
1.
package com.briup.pojo;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
@Component("target")
//@Controller
//@Service
//@Repository
public class BookServiceImpl
implements BookService{
@Override
public void saveBook(long id, String name) {
// TODO Auto-generated method stub
System.out.println("saveBook....");
//int i=10/0;
}
@Override
public String get(long id) {
// TODO Auto-generated method stub
System.out.println("get....");
return "test...ok";
}
@Override
public void list() {
// TODO Auto-generated method stub
System.out.println("list....");
}
@Override
public void setTest() {
// TODO Auto-generated method stub
System.out.println("set.....");
}
@Override
public int getAge() {
// TODO Auto-generated method stub
System.out.println("getAge()....");
return 23;
}
}
package com.briup.pojo;
import org.springframework.stereotype.Component;
@Component("target1")
public class ProductService {
public void saveProduct(long id,String name){
System.out.println("saveProduct...");
}
public int getProduct(){
System.out.println("getProduct....");
return 33;
}
}
2.自定义通知类
package com.briup.aop.spring.AnnoAopConfig;
import org.aspectj.lang.JoinPoint;
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;
import org.springframework.stereotype.Component;
/*
* 自定义通知类(自定义的方法)
* @Aspect表示单前类中的方法全是
* 作用切面上的通知
* 1.注解的方式构建切面(方法)
* 2.通知上面加入注解
*/
@Component
@Aspect
public class AnnoNoticeAdvice {
/*
* 构建切面的方法,切面的名字
* 就是methodName(),
* 该方法不使用
*/
//@Pointcut(value="")
@Pointcut("execution(* com.briup.pojo.*.save*(..))")
public void mypointcut(){}
/*
* 前置通知,
* 参数必须是joinpoint
* @Before注解该方法前置通知
* 参数是切面的名字
*/
@Before("mypointcut()")
public void beforeTest(JoinPoint point){
System.out.println("before......");
}
/*
* 后置通知
*/
@After("mypointcut()")
public void after(JoinPoint point){
//获取方法的镜像
// System.out.println(point.getSignature());
// //获取方法镜像的名字
// System.out.println(
// point.getSignature().getName());
//获取目标对象方法执行的参数
// System.out.println(
// Arrays.toString(point.getArgs()));
//获取目标对象
// System.out.println(point.getTarget());
// System.out.println(point.getThis());
System.out.println("after....");
}
@AfterReturning("mypointcut()")
public void afterReturn(JoinPoint point){
System.out.println("after1.....");
}
@Around("mypointcut()")
public Object
around(ProceedingJoinPoint point){
// System.out.println(point.getTarget());
// System.out.println(point.getThis());
// System.out.println(point.getSignature());
// System.out.println(point.getArgs());
Object obj=null;
try {
System.out.println("before.....");
//执行目标对象中的方法
obj=point.proceed();
System.out.println("after....");
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
/*
* 异常通知的方法
* 第一个参数joinPoint
* 第二个参数异常类
* @AfterThrowing中throwing对应的名字和参数
* 异常的名字一致
*/
@AfterThrowing(value="mypointcut()",
throwing="ex")
public void
throwE(JoinPoint point,Exception ex){
System.out.println(
"exception..."+ex.getMessage());
}
}
3.配置文件
4.测试类:
package com.briup.aop.spring.AnnoAopConfig;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.briup.pojo.BookService;
import com.briup.pojo.ProductService;
public class AnnoaopConfigTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext(
"com/briup/aop/spring/AnnoAopConfig/annoaopconfig.xml");
BookService bs=
cp.getBean("target",BookService.class);
bs.saveBook(1, "lisi");
bs.list();
// ProductService ps=
// cp.getBean("target1",ProductService.class);
// ps.saveProduct(1, "lisi");
// ps.getProduct();
}
}