package com.itheima.aspect;

public class MyAspect {
public void check_Permissions(){
System.out.println("模拟检查权限...");
}
public void log() {
// TODO Auto-generated method stub
System.out.println("记录日志");
}
}

  

package com.itheima.aspect;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import com.itheima.jdk.UserDao; public class JdkProxy implements InvocationHandler{
private UserDao userDao;
public Object createProxy(UserDao userDao){
this.userDao=userDao;
ClassLoader classLoader=JdkProxy.class.getClassLoader();
Class[]clazz = userDao.getClass().getInterfaces();
return Proxy.newProxyInstance(classLoader, clazz, this); }
@Override
public Object invoke(Object proxy,Method method,Object[]args)
throws Throwable{
MyAspect myAspect = new MyAspect();
myAspect.check_Permissions();
Object obj = method.invoke(userDao,args);
myAspect.log();
return obj;
}
}

  

package com.itheima.aspect;

import com.itheima.jdk.UserDao;
import com.itheima.jdk.UserDaoImpl; public class JdkTest {
public static void main(String[] args) {
JdkProxy jdkProxy= new JdkProxy();
UserDao userDao = new UserDaoImpl();
UserDao userDao1= (UserDao)jdkProxy.createProxy(userDao);
userDao1.addUser();
userDao1.deleteUser();
}
}

  

AOP动态代理方法的实现如上,不过总体来说还是比较麻烦,要修改的地方也太多。

后来有人开发了aspectJ工具,通过aspectJ,可以方便的使用切面,把代理类和实现类与代理类之间的耦合解除。

aspectJ有两种实现方式,一种是xml,一种是注解。

这里要注意需要导入aspectJ的相关包

方式1:通过xml实现

  将代理类和实现类与代理类之间的调用关系,全部写进xml中:

即以上的代码修改一下:

切面:

  

package com.itheima.aspectj.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint; public class MyAspect {
public void myBefore(JoinPoint joinPoint){
System.out.println("前置通知");
System.out.println("目标类是:"+joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
}
public void myAfterReturning(JoinPoint joinPoint){
System.out.println("后置通知");
System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
}
public Object myAround(ProceedingJoinPoint joinPoint)
throws Throwable{
System.out.println("环绕开始:执行方法之前,模拟开启事务");
Object object=joinPoint.proceed();
System.out.println("环绕结束:执行方法之后,模拟关闭事务");
return object;
}
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("异常通知:"+"出错了"+e.getMessage());
System.out.println("目标类是:"+joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
}
public void myAfter(JoinPoint joinPoint){
System.out.println("最终通知:模拟方法结束后释放资源");
}
}

  

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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<bean id = "userDao" class = "com.itheima.jdk.UserDaoImpl"/>
<bean id = "myAspect" class = "com.itheima.aspectj.xml.MyAspect"/>
<aop:config>
<aop:aspect id = "aspect" ref = "myAspect">
<aop:pointcut expression = "execution(* com.itheima.jdk.*.*(..))"
id = "myPointCut"/>
<aop:before method = "myBefore" pointcut-ref="myPointCut"/>
<aop:after-returning method="myAfterReturning"
pointcut-ref = "myPointCut" returning = "returnVal"/>
<aop:around method="myAround" pointcut-ref="myPointCut"/>
<aop:after-throwing method = "myAfterThrowing"
pointcut-ref = "myPointCut" throwing="e"/>
<aop:after method="myAfter" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
</beans>

测试类:

package com.itheima.aspectj.xml;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.jdk.UserDao;
public class AspectjXmlTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("com/itheima/aspectj/xml/applicationContext.xml");
UserDao userDao= (UserDao) applicationContext.getBean("userDao");
userDao.addUser();
userDao.deleteUser();
}
}

  

执行结果:

前置通知
目标类是:com.itheima.jdk.UserDaoImpl@59309333
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.addUser()
环绕开始:执行方法之前,模拟开启事务
添加用户
最终通知:模拟方法结束后释放资源
环绕结束:执行方法之后,模拟关闭事务
后置通知
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.addUser()
前置通知
目标类是:com.itheima.jdk.UserDaoImpl@59309333
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.deleteUser()
环绕开始:执行方法之前,模拟开启事务
删除用户
最终通知:模拟方法结束后释放资源
环绕结束:执行方法之后,模拟关闭事务
后置通知
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.deleteUser()

  

aspectJ减少了动态代理实现中出现的代码臃肿,但是,需要修改spring的配置文件,不是很好。

于是衍生了注解方式实现AOP,完美解决了修改spring配置文件的问题。

package com.itheima.aspectj.annotation;

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
@Component
public class MyAspect {
//defined the pointcut
@Pointcut("execution(* com.itheima.jdk.*.*(..))")
private void myPointCut(){}
//pre-notification
@Before("myPointCut()")
public void myBefore(JoinPoint joinPoint){
System.out.println("前置通知");
System.out.println("目标类是:"+joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
}
//after-notification
@AfterReturning(value="myPointCut()")
public void myAfterReturning(JoinPoint joinPoint){
System.out.println("后置通知");
System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
}
//around-notification
@Around("myPointCut()")
public Object myAround(ProceedingJoinPoint joinPoint)
throws Throwable{
System.out.println("环绕开始:执行方法之前,模拟开启事务");
Object object=joinPoint.proceed();
System.out.println("环绕结束:执行方法之后,模拟关闭事务");
return object;
}
@AfterThrowing(value="myPointCut()",throwing="e")
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("异常通知:"+"出错了"+e.getMessage());
System.out.println("目标类是:"+joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
}
@After("myPointCut()")
public void myAfter(JoinPoint joinPoint){
System.out.println("最终通知:模拟方法结束后释放资源");
}
}

  

	<context:component-scan base-package="com.itheima" />
<aop:aspectj-autoproxy />

  

public class AspectjXmlTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("com/itheima/aspectj/annotation/applicationContext.xml");
UserDao userDao= (UserDao) applicationContext.getBean("userDao");
userDao.addUser();
userDao.deleteUser();
}
}

  

spring-AOP动态代理,以及aspectJ的xml配置或注解配置方法,各个拦截器的使用顺序的更多相关文章

  1. Spring AOP动态代理原理与实现方式

    AOP:面向切面.面向方面.面向接口是一种横切技术横切技术运用:1.事务管理: (1)数据库事务:(2)编程事务(3)声明事物:Spring AOP-->声明事物   2.日志处理:3.安全验证 ...

  2. spring AOP 动态代理和静态代理以及事务

    AOP(Aspect Oriented Programming),即面向切面编程 AOP技术,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装 ...

  3. Spring AOP 动态代理 缓存

    Spring AOP应用:xml配置及注解实现. 动态代理:jdk.cglib.javassist 缓存应用:高速缓存提供程序ehcache,页面缓存,session缓存 项目地址:https://g ...

  4. spring aop 动态代理批量调用方法实例

    今天项目经理发下任务,需要测试 20 个接口,看看推送和接收数据是否正常.因为对接传输的数据是 xml 格式的字符串,所以我拿现成的数据,先生成推送过去的数据并存储到文本,以便验证数据是否正确,这时候 ...

  5. Spring AOP动态代理

    出现org.springframework.aop.framework.ProxyFactoryBean cannot be cast to 错误 在类型转换的时候, 调用getObject()方法, ...

  6. Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题

    Spring AOP底层的动态代理实现有两种方式:一种是JDK动态代理,另一种是CGLib动态代理. JDK动态代理 JDK 1.3版本以后提供了动态代理,允许开发者在运行期创建接口的代理实例,而且只 ...

  7. Spring Aop 动态代理失效分析

    1. Spring Aop 原理 Spring Aop 通过动态代理创建代理对象,在调用代理对象方法前后做增强. 2. Transactional, Async 注解失效? 当在动态代理方法中调用当前 ...

  8. Spring学习笔记之aop动态代理(3)

    Spring学习笔记之aop动态代理(3) 1.0 静态代理模式的缺点: 1.在该系统中有多少的dao就的写多少的proxy,麻烦 2.如果目标接口有方法的改动,则proxy也需要改动. Person ...

  9. spring AOP 之二:@AspectJ注解的3种配置

    @AspectJ相关文章 <spring AOP 之二:@AspectJ注解的3种配置> <spring AOP 之三:使用@AspectJ定义切入点> <spring ...

随机推荐

  1. linux系统中RAID10磁盘冗余阵列配置

    介绍:RAID10:需要至少四块(含)硬盘,兼具速度和安全性,但成本很高,RAID10用两个磁盘做RAID0,用其他两个做RAID1当备份. 配置流程: 第一步:在原有基础上为磁盘再填入五块磁盘(至少 ...

  2. v-radio

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  3. v-bind 绑定属性

    与mustache相区别,他是对内容(content内部)进行修改的.v-bind的语法糖写法是   : v-bind 动态绑定class属性:v-bind:class="对象名" ...

  4. Shuffle 机制

    1. 概述 Map 方法之后,Reduce 方法之前的数据处理过程称之为 Shuffle. 2. Partition 分区 需求:要求将统计结果按照条件输出到不同文件中(分区).比如:将统计结果按照手 ...

  5. hdoj2594(kmp算法next数组的应用)

    题目链接:https://vjudge.net/problem/HDU-2594 题意:给定两个字符串s1.s2,求s1的前缀和s2的后缀的最长公共部分. 思路: 将s1和s2连接后求nex数组即可, ...

  6. wordpress 图片上传时发生了错误,请稍后再试 的解决办法

    前一天网站还是好好的,仅一天过后就显示图片无法上传,百思不得其解 上下百度,大多数帖子提供的解决办法对我都不适用,继续搜,最后发现一篇帖子中提到是wp-config的编码格式问题 想到昨天刚好修改了下 ...

  7. SysTick 定时实验(非中断)

    实验目的:利用 SysTick 产生 1s 的时基,LED 以 1s 的频率闪烁. 编程要点 1.设置重装载寄存器的值 2.清除当前数值寄存器的值 3.配置控制与状态寄存器 过程 我们创建了两个文件: ...

  8. harbor关联k8s

    第一步 在harbor上创建用户,项目,将用户添加到对应项目中,并赋予用户项目管理者或者开发人员权限,使其对镜像仓库有读写权限. 本次部署创建用户liusw,密码Lsw123456,邮箱8730017 ...

  9. (七)lucene之中文检索和高亮显示以及摘要

    前提:本章节使用lucene5.3.0版本,luke也是此版本的. 1.1  生成索引 package com.shyroke.lucene; import java.io.IOException; ...

  10. 原生js上传图片遇到的坑(axios封装)

    后台给我写了一个上传图片的接口,自己用form表单测试成功 接口可以正常跳转 测试的代码: <!doctype html> <html lang="en"> ...