目录
目录
使用aspectJ框架完成aop的实现
新建maven项目
加入maven依赖
spring容器,创建 对象
Student类
一.前置通知的使用@Before
1.创建目标类(接口和它的实现类)
2.切面类
3.MyApp
二.后置通知的使用@AfterReturning
1.创建目标类(接口和实现类)
2.切面类
3.MyApp
三.环绕通知(@Around)
1.创建目标对象(接口和实现类)
2.创建切面类
3.MyApp
四.异常通知@AfterThrowing
1.创建目标对象(接口和实现类)
2.创建切面类
3.MyAPP
五.最终通知@After
1.创建目标类(接口和实现类)
2.切面类
3.MyApp
六.@Pointcut切入点的复用
1.创建目标类(接口和实现类)
2. 切面类
3.MyApp
使用aspectJ框架完成aop的实现
新建maven项目 加入maven依赖ch05-aop-aspectj:使用aspectj框架实现aop。 使用aop:目的是给已经存在的一些类和方法,增加额外的功能。前提是不改变原来类的代码。 使用aspectj实现aop的基本步骤: 1.新建maven项目 2.加入依赖 1)spring依赖 2)aspect依赖 3)junit单元测试 3.创建目标类:接口和它的实现类 要做的是给类中的方法增加功能 4.创建切面类:普通类 1)在类的上面加入 @Aspect 2)在类中定义方法,方法就是切面要执行的功能代码 在方法的上面加入aspectj中的通知注解,例如 @Before 有需要指定切入点表达式execution() 5.创建spring的配置文件,声明对象,把对象交给容器统一管理。 声明对象你可以使用注解,或者xml配置文件1)声明目标对象 2)声明切面类对象 3)声明aspectj框架中的自动代理生成器标签。 自动代理生成器:用来完成代理对象的自动创建功能。 6.创建测试类,从spring容器中获取目标对象(实际上就是代理对象)。 通过代理实现方法,实现aop的功能增强。
spring容器,创建 对象4.0.0 edu.tjdz ch05-aop-sapectj1.0-SNAPSHOT UTF-8 1.8 1.8 junit junit4.11 test org.springframework spring-context5.2.5.RELEASE org.springframework spring-aspects5.2.5.RELEASE
Student类
package edu.tjdz.ba02; public class Student { private String name; private int age; public Student(){ System.out.println("Spring会调用类的无参数构造方法创建对象"); } public void setEmail(String email){ System.out.println("setEmail="+email); } public void setName(String name) { System.out.println("setName="+name); this.name = name.toUpperCase(); } public void setAge(int age) { System.out.println("setAge="+age); this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + ''' + ", age=" + age + '}'; } }一.前置通知的使用@Before
1.创建目标类(接口和它的实现类)首先是创建好切面类后在切面类的上面加入@Aspect注解
在方法之上加入@Before表示前置通知,它有属性value,其值是一个切入点表达式:
参数包括:(红色表示为必须写的)
execution("修饰符 返回值类型 包.类.方法名(参数..) throws异常")
修饰符(举例):一般省略
* 任意
public 公共访问
返回值(举例):
void 无返回值
String 返回值是字符串类型
* 返回值任意
包(举例):
com.xx.user.dao 固定包
com.xx.*.dao com.xx下的任意包中的dao包
com.xx.user.dao.. 包括dao下所有子包中
类(举例):
UserDaoImpl 具体类
User* 以User开头类
*User 以User结尾类
* 任意类
方法(举例):
addUser 具体方法
* 任意方法
*User 以add结尾方法
add* 以add开头方法
参数(无参):
() 无参
(..) 任意参数
(String,int) 1个String和1个int类型的参数
(int) 1个int类型参数
throws,可省略一般不写
在@aspect类中会有使用:
Aspect类的命名及其方法的命名详见标题2切面类中的注释
例如:
@Aspect
public class MyAspectJ{
@Before(* * edu.tjdz.*.*.doSome(..) Exception)
public void myBefore(){
System.out.println("前置通知方法");
}
}
package edu.tjdz.ba01; public interface SomeService { void doSome(String name,Integer age); }
package edu.tjdz.ba01; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name,Integer age) { //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间 System.out.println("====目标方法doSome()===="); } public void doOther(String name,Integer age) { //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间 System.out.println("====目标方法doOther()===="); } }2.切面类
package edu.tjdz.ba01; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import java.util.Date; @Aspect public class MyAspect { @Before(value="execution(* *..SomeServiceImpl.doSome(String,Integer))") public void myBefore2(JoinPoint jp){ //获取方法的完整定义 System.out.println("方法的签名(定义)="+jp.getSignature()); System.out.println("方法的名称="+jp.getSignature().getName()); //获取方法的实参 Object [] args = jp.getArgs(); for(Object arg :args){ System.out.println("参数="+arg); } //就是在切面要执行功能代码 System.out.println("5====>前置通知,切面功能:在目标方法之前输出执行时间:"+new Date()); } }3.MyApp
有接口的默认采用的是JDK的动态代理
若想在有接口的情况下依旧使用Cglib的代理方式,需要在spring配置文件中加入
package edu.tjdz; import edu.tjdz.ba01.SomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest01 { @Test public void test01(){ String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取目标对象 SomeService proxy = (SomeService) ac.getBean("someService"); //proxy:com.sun.proxy.$Proxy0 //proxy:com.sun.proxy.$Proxy8 : JDK的动态代理 System.out.println("proxy:"+proxy.getClass().getName()); //通过代理对象执行方法,实现目标方法的执行,增强了功能 proxy.doSome("李四",20); } }二.后置通知的使用@AfterReturning
1.创建目标类(接口和实现类)在方法执行之后执行
package edu.tjdz.ba02; public interface SomeService { void doSome(String name, Integer age); String doOther(String name,Integer age); Student doOther2(String name,Integer age); }
package edu.tjdz.ba02; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name,Integer age) { //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间 System.out.println("====目标方法doSome()===="); } @Override public String doOther(String name, Integer age) { System.out.println("====目标方法doOther()===="); return "abcd"; } @Override public Student doOther2(String name, Integer age) { Student student = new Student(); student.setName("lisi"); student.setAge(20); return student; } }2.切面类
package edu.tjdz.ba02; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; @Aspect public class MyAspect { @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther2(..))", returning = "res") public void myAfterReturing(JoinPoint jp,Object res){ //Object res:目标方法执行之后的返回值,根据返回值做你的切面的功能处理 System.out.println("后置通知方法的定义:"+jp.getSignature()); System.out.println("后置通知:在目标方法之后执行的,获取的返回值是:"+res); if(res.equals("abcd")){ //制作一些功能 }else{ //做其他功能 } //修改目标方法的返回值,看一下是否会影响 最后的方法调用的结果 if(res != null){ res = "Hello Aspectj"; } } @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther2(..))", returning = "res") public void myAfterReturing2(Object res){ //Object res:是目标方法执行后的返回值,根据返回值做你的切面的处理功能 System.out.println("后置通知:在目标方法之后执行的,获取的返回值是:"+res); //修该目标方法的返回值,看一下是否会影响 最后调用方法输出的结果 //如果修改了res的内容,属性值等,是不是会影响最后的调用结果呢 Student student = new Student(); student.setName("张飞"); student.setAge(60); res = student; } }3.MyApp
package edu.tjdz; import edu.tjdz.ba02.SomeService; import edu.tjdz.ba02.Student; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest02 { @Test public void test01(){ String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取目标对象 SomeService proxy = (SomeService) ac.getBean("someService"); //通过代理对象执行方法,实现目标方法执行时,增强了功能 String str = proxy.doOther("张三",20); System.out.println(str); } @Test public void test02(){ String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取目标对象 SomeService proxy = (SomeService) ac.getBean("someService"); //通过代理对象执行方法,实现目标方法执行时,增强了功能 Student str = proxy.doOther2("张三",20); System.out.println(str); } }三.环绕通知(@Around)
1.创建目标对象(接口和实现类)还绕通知等同于JDK动态代理的,InvocationHandler接口
环绕通知:经常做事务,在目标方法之前开启事务,执行目标方法,在目标方法之后提交事务环绕通知方法定义格式 * 1.public * 2.必须有一个返回值,推荐使用Object * 3.方法名称自定义 * 4.方法有参数,固定参数 ProceedingJoinPoint,相当于invoke中的Method()
package edu.tjdz.ba03; import edu.tjdz.ba02.Student; public interface SomeService { void doSome(String name, Integer age); String doOther(String name, Integer age); Student doOther2(String name, Integer age); String doFirst(String name,Integer age); }
package edu.tjdz.ba03; import edu.tjdz.ba02.Student; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name,Integer age) { //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间 System.out.println("====目标方法doSome()===="); } @Override public String doOther(String name, Integer age) { System.out.println("====目标方法doOther()===="); return "abcd"; } @Override public Student doOther2(String name, Integer age) { Student student = new Student(); student.setName("lisi"); student.setAge(20); return student; } @Override public String doFirst(String name, Integer age) { System.out.println("==========业务方法doFirst()======="); return "doFirst"; } }2.创建切面类
package edu.tjdz.ba03; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import java.util.Date; @Aspect public class MyAspect { @Around(value = "execution(* *..SomeServiceImpl.doFirst(..))") public Object myAround(ProceedingJoinPoint pjp) throws Throwable { String name = ""; //获取第一个参数值 Object [] args = pjp.getArgs(); if(args != null && args.length >1){ Object arg = args[0]; name= (String)arg; } //环绕通知 Object result = null; System.out.println("环绕通知:在目标方法之前,输出时间:"+new Date()); //1.目标方法的调用 if("zhangsan".equals(name)){ //符合条件,调用目标方法 result = pjp.proceed(); //method.invoke(); Object result = doFirst(); } System.out.println("环绕通知:在目标方法之后,提交事务"); //2.在目标方法的前或者后加入功能 //修改目标方法的执行结果,影响方法的最后调用结果 if(result != null){ result = "Hello AspectJ AOP"; } //返回方法的执行结果 return result; } }3.MyApp
package edu.tjdz; import edu.tjdz.ba03.SomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest03 { @Test public void test01(){ String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取目标对象 SomeService proxy = (SomeService) ac.getBean("someService"); String str = proxy.doFirst("zhangsan",20); //proxy.invoke(); //String str = proxy.myAround("zhangsan",20); System.out.println(str); } }四.异常通知@AfterThrowing 1.创建目标对象(接口和实现类)
package edu.tjdz.ba04; import edu.tjdz.ba02.Student; public interface SomeService { void doSome(String name, Integer age); String doOther(String name, Integer age); Student doOther2(String name, Integer age); String doFirst(String name, Integer age); void doSecond(); }
package edu.tjdz.ba04; import edu.tjdz.ba02.Student; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name,Integer age) { //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间 System.out.println("====目标方法doSome()===="); } @Override public String doOther(String name, Integer age) { System.out.println("====目标方法doOther()===="); return "abcd"; } @Override public Student doOther2(String name, Integer age) { Student student = new Student(); student.setName("lisi"); student.setAge(20); return student; } @Override public String doFirst(String name, Integer age) { System.out.println("==========业务方法doFirst()======="); return "doFirst"; } @Override public void doSecond() { //System.out.println(10/0); System.out.println("=========执行业务方法doSecond()=="); } }2.创建切面类
package edu.tjdz.ba04; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; @Aspect public class MyAspect { @AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))", throwing = "ex") public void myAfterThrowing(Exception ex){ System.out.println("异常通知:方法发生异常时,执行:"+ex.getMessage()); //发送邮件,短信,通知开发人员 } }3.MyAPP
package edu.tjdz; import edu.tjdz.ba04.SomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest04 { @Test public void test01(){ String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取目标对象 SomeService proxy = (SomeService) ac.getBean("someService"); //通过代理对象执行方法,实现目标方法执行时,增强了功能 proxy.doSecond(); } }五.最终通知@After 1.创建目标类(接口和实现类)
package edu.tjdz.ba05; import edu.tjdz.ba02.Student; public interface SomeService { void doSome(String name, Integer age); String doOther(String name, Integer age); Student doOther2(String name, Integer age); String doFirst(String name, Integer age); void doSecond(); void doThird(); }
package edu.tjdz.ba05; import edu.tjdz.ba02.Student; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name,Integer age) { //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间 System.out.println("====目标方法doSome()===="); } @Override public String doOther(String name, Integer age) { System.out.println("====目标方法doOther()===="); return "abcd"; } @Override public Student doOther2(String name, Integer age) { Student student = new Student(); student.setName("lisi"); student.setAge(20); return student; } @Override public String doFirst(String name, Integer age) { System.out.println("==========业务方法doFirst()======="); return "doFirst"; } @Override public void doSecond() { //System.out.println(10/0); System.out.println("=========执行业务方法doSecond()=="); } @Override public void doThird() { System.out.println("执行业务方法doThird()"+10/0); } }2.切面类
package edu.tjdz.ba05; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; @Aspect public class MyAspect { @After(value = "execution(* *..SomeServiceImpl.doThird(..))") public void myAfter() { System.out.println("执行最终通知:总是会被执行"); //一般做资源清理工作的 } }3.MyApp
package edu.tjdz; import edu.tjdz.ba05.SomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest05 { @Test public void test01(){ String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取目标对象 SomeService proxy = (SomeService) ac.getBean("someService"); //通过代理对象执行方法,实现目标方法执行时,增强了功能 proxy.doThird(); } }六.@Pointcut切入点的复用
1.创建目标类(接口和实现类)定义和管理切入点,如果你的项目中有多个切入点表达式是重复的,可以复用的。
@Pointcut(value = "execution(* *..SomeServiceImpl.doThird(..))") private void mypt(){ //无需代码 }放其他通知想使用这个通知的时候,直接给value值给一个方法名就可以使用
@Before(value = "mypt()") public void myBefore() { System.out.println("前置通知,在目标方法之前执行的"); }
package edu.tjdz.ba06; import edu.tjdz.ba02.Student; public interface SomeService { void doSome(String name, Integer age); String doOther(String name, Integer age); Student doOther2(String name, Integer age); String doFirst(String name, Integer age); void doSecond(); void doThird(); }
package edu.tjdz.ba06; import edu.tjdz.ba02.Student; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name,Integer age) { //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间 System.out.println("====目标方法doSome()===="); } @Override public String doOther(String name, Integer age) { System.out.println("====目标方法doOther()===="); return "abcd"; } @Override public Student doOther2(String name, Integer age) { Student student = new Student(); student.setName("lisi"); student.setAge(20); return student; } @Override public String doFirst(String name, Integer age) { System.out.println("==========业务方法doFirst()======="); return "doFirst"; } @Override public void doSecond() { //System.out.println(10/0); System.out.println("=========执行业务方法doSecond()=="); } @Override public void doThird() { System.out.println("执行业务方法doThird()"); } }2. 切面类
package edu.tjdz.ba06; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyAspect { @After(value = "execution(* *..SomeServiceImpl.doThird(..))") public void myAfter() { System.out.println("执行最终通知:总是会被执行"); //一般做资源清理工作的 } @Before(value = "mypt()") public void myBefore() { System.out.println("前置通知,在目标方法之前执行的"); } @Pointcut(value = "execution(* *..SomeServiceImpl.doThird(..))") private void mypt(){ //无需代码 } }3.MyApp
package edu.tjdz; import edu.tjdz.ba06.SomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest06 { @Test public void test01(){ String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); //从容器中获取目标对象 SomeService proxy = (SomeService) ac.getBean("someService"); System.out.println("proxy:"+proxy.getClass().getName()); //通过代理对象执行方法,实现目标方法执行时,增强了功能 proxy.doThird(); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)