
目录
目录
使用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条)