在Spring中使用AspectJ实现AOP
在spring中使用aspectj有2种方式:
- xml配置
- 注解配置(推荐)
这2种方式需要添加的jar包都一样(待修改):
- spring-aop.RELEASE.jar
- aspectjweaver.jar
在spring中使用aspectj,不需要添加aspectjrt.jar,也不需要专门的ajc编译器,使用javac编译即可。
xml配置方式
(1)目标接口、目标类
新建包com.chy.dao,包下新建接口UserDao、实现类UserDaoImpl:
public interface UserDao {
public void addUser();
public void deleteUser();
}
public class UserDaoImpl implements UserDao{
@Override
public void addUser() {
System.out.println("正在添加用户...");
} @Override
public void deleteUser() {
System.out.println("正在删除用户...");
}
}
(2)切面
新建包com.chy.aspect,包下新建类UserDaoAspect:
public class UserDaoAspect {
//前置通知要调用的方法
public void before(){
System.out.println("正在执行前置通知...");
} //后置通知要调用的方法
public void after(){
System.out.println("正在执行后置通知...");
} //返回通知要调用的方法
public void afterReturning(Object obj){
System.out.println("正在执行返回通知...");
System.out.println("目标方法的返回值是:"+obj);
} // 异常通知要调用的方法
public void afterThrowing(JoinPoint point,Exception e){
System.out.println("异常信息:"+e.getMessage());
}
}
(3)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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--目标对象-->
<bean name="userDaoImpl" class="com.chy.dao.UserDaoImpl" /> <!--切面-->
<bean name="userDaoAspect" class="com.chy.aspect.UserDaoAspect" /> <!--AOP配置-->
<aop:config>
<!--全局切入点,所有切面都可以引用。配置切入点只能用id,不能用name -->
<!-- <aop:pointcut id="pointCut" expression="execution(* com.chy.dao.UserDaoImpl.*(..))" /> --> <!--一个<aop:aspect>配置一个切面-->
<aop:aspect ref="userDaoAspect">
<!--局部切入点,只能在此切面中引用-->
<aop:pointcut id="pointCut" expression="execution(* com.chy.dao.UserDao.*(..))" /> <!--前置通知-->
<aop:before method="before" pointcut-ref="pointCut" />
<!--可以引用切入点,也可以现配-->
<!-- <aop:before method="before" pointcut="execution(* com.chy.dao.UserDao.*(..))"/> --> <!--后置通知-->
<aop:after method="after" pointcut-ref="pointCut" /> <!--返回通知-->
<!--如果要使用目标方法的返回值,可以用returning要将目标方法的返回值传递给返回通知要调用的方法的哪个形参-->
<aop:after-returning method="afterReturning" pointcut-ref="pointCut" returning="obj"/> <!--异常通知-->
<!--如果要使用捕获的异常对象,可以用throwing指定要将异常对象传递给哪个形参-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointCut" throwing="e"/> </aop:aspect> </aop:config> </beans>
5种通知对应的方法都可以传递JoinPoint型的参数,不用传递实参,只有目标方法的返回值、捕获的异常需要传实参。
returning是返回通知的特有属性,throwing是异常通知的特有属性。
环绕通知
环绕通知与其它通知有重叠,通常不与其它通知一起使用。
// 环绕通知
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//前增强
System.out.println("正在执行前增强...");
//调用目标方法
Object object=proceedingJoinPoint.proceed();
//后增强
System.out.println("正在执行后增强...");
return object;
}
<!--环绕通知-->
<!--ProceedingJoinPoint是JoinPoint的子类,不必手动传参-->
<aop:around method="around" pointcut-ref="pointCut" />
注解配置方式
(1)目标接口、目标类
public interface UserDao {
public void addUser();
public void deleteUser();
}
@Repository
public class UserDaoImpl implements UserDao{
@Override
public void addUser() {
System.out.println("正在添加用户...");
} @Override
public void deleteUser() {
System.out.println("正在删除用户...");
}
}
(2)切面
@Component
@Aspect
public class UserDaoAspect {
//配置切入点
@Pointcut("execution(* com.chy.dao.UserDao.*(..))")
private void pointCut(){} /*
前置通知
@Before(value="pointCut()"),只有一个属性时可以只写属性值
@Before("execution(* com.chy.dao.UserDao.*(..))"),属性值可以引用切入点,也可以现配
*/
@Before("pointCut()")
public void before(){
System.out.println("正在执行前置通知...");
} //后置通知
@After("pointCut()")
public void after(){
System.out.println("正在执行后置通知...");
} //返回通知。可传递目标方法的返回值。
@AfterReturning(value = "pointCut()",returning = "obj" )
public void afterReturning(Object obj){
System.out.println("正在执行返回通知...");
System.out.println("目标方法的返回值是:"+obj);
} // 异常通知。可传递异常对象。
@AfterThrowing(value = "pointCut()",throwing = "e")
public void afterThrowing(JoinPoint point,Exception e){
System.out.println("异常信息:"+e.getMessage());
}
}
环绕通知:
// 环绕通知
@Around("pointCut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//前增强
System.out.println("正在执行前增强...");
//调用目标方法
Object object=proceedingJoinPoint.proceed();
//后增强
System.out.println("正在执行后增强...");
return object;
}
(3)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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--使用包扫描,要扫描多个包时用逗号分隔-->
<context:component-scan base-package="com.chy.dao,com.chy.aspect" /> <!--启用AspectJ的注解-->
<aop:aspectj-autoproxy />
</beans>
使用注解十分方便,xml文件也更加简洁,推荐。
使用
不管是xml方式,还是注解方式,使用时都是一样的:
(1)如果目标类实现了接口,不管切入点配置为接口、还是实现类:
execution(* com.chy.dao.UserDao.*(..))
execution(* com.chy.dao.UserDaoImpl.*(..))
使用时都只能使用接口(代理的是接口,不是具体的实现类):
UserDao userDao=applicationContext.getBean("userDaoImpl", UserDao.class);
userDao.addUser();
红色标出的两处都只能使用接口。
(2)如果目标类没有实现接口,那切入点只能配置为目标类:
execution(* com.chy.dao.UserDaoImpl.*(..))
使用时自然只能使用目标类:
UserDaoImpl userDao=applicationContext.getBean("userDaoImpl", UserDaoImpl.class);
userDao.addUser();
调用方法时会自动增强。
AOP常见术语
- Joinpoint (连接点):目标类中的所有方法
- Pointcut(切入点):目标类中被增强的方法。有时候我们只增强目标类的部分方法。
- Weaving(织入):把增强应用到目标对象创建代理对象的过程。spring aop采用动态代理织入,aspectj采用在编译期、类装载期织入。
在Spring中使用AspectJ实现AOP的更多相关文章
- Spring中基于xml的AOP
1.Aop 全程是Aspect Oriented Programming 即面向切面编程,通过预编译方式和运行期动态代理实现程序功能的同一维护的一种技术.Aop是oop的延续,是软件开发中的 一个热点 ...
- 详谈 Spring 中的 IOC 和 AOP
这篇文章主要讲 Spring 中的几个点,Spring 中的 IOC,AOP,下一篇说说 Spring 中的事务操作,注解和 XML 配置. Spring 简介 Spring 是一个开源的轻量级的企业 ...
- Spring框架(6)---AspectJ实现AOP
AspectJ实现AOP 上一篇文章Spring框架(4)---AOP讲解铺垫,讲了一些基础AOP理解性的东西,那么这篇文章真正开始讲解AOP 通过AspectJ实现AOP要比普通的实现Aop要方便的 ...
- Spring实战(十二) Spring中注入AspectJ切面
1.Spring AOP与AspectJ Spring AOP与AspectJ相比,是一个功能比较弱的AOP解决方案. AspectJ提供了许多它不能支持的类型切点,如在创建对象时应用通知,构造器切点 ...
- 如何快速理解Spring中的DI和AOP
前言 Spring框架通过POJO最小侵入性编程.DI.AOP.模板代码手段来简化了Java 开发,简化了企业应用的开发.POJO和模板代码相对来说好理解,本篇重点解读下DI和AOP. 一 DI DI ...
- 理解Spring中的IOC和AOP
我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式 IOC就是典型的工厂模式,通过ses ...
- spring中基于注解使用AOP
本文内容:spring中如何使用注解实现面向切面编程,以及如何使用自定义注解. 一个场景 比如用户登录,每个请求发起之前都会判断用户是否登录,如果每个请求都去判断一次,那就重复地做了很多事情,只要是有 ...
- Spring中的IOC\DI\AOP等概念的简单学习
IoC(Inversion of Control,控制反转).这是spring的核心,贯穿始终, 所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系.Spr ...
- Spring AOP报错处理 Can not set field to $Proxy 在spring中使用事物或AOP遇到的错误
[转] 解决方法: http://forum.springsource.org/showthread.php?85016-IllegalArgumentException-with-Applicati ...
随机推荐
- 考勤打卡机导出的excel考勤时间表如何生成实用的考勤表
该excel表有如下结构 姓名\日期 周1 周2 周3 周4 周5 张三 7:3518:02 7:3518:02 7:46 17:56 李四 7:3518:02 7:02 18:00 18:02 ...
- C# Area区域配置,修改默认路由
1.右键项目新建文件夹 Areas 2.先把项目分类包好,建两个文件夹,放Controller和View,Model也可以放在这里 因为项目启动默认打开的是Home/Index ,我把它放在了Webs ...
- 移除 WordPress 自动加载的 jQuery,使用自定义 jQuery 版本
WordPress 使用的 jQuery 版本由于需要考虑到很多安全稳定的因素,所以一般不会使用最新版本的 jQuery, 可以通过以下方式移除 WordPress 自定加载的 jQuery,并加载自 ...
- Consider defining a bean of type 'com.*.*.feign.*FeignClient' in your configuration.
Description: Field *FeignClient in com.*.*.service.* required a bean of type '***********' that coul ...
- 查找算法(4)--Fibonacci search--斐波那契查找
1.斐波那契查找 (1)说明 在介绍斐波那契查找算法之前,我们先介绍一下很它紧密相连并且大家都熟知的一个概念——黄金分割. 黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二, ...
- mac环境更新node版本
执行命令: 清除node的cache(清除node的缓存) sudo npm cache clean -f 安装"n"版本管理工具,管理node(没有错,就是n) sudo npm ...
- 【Docker学习之一】初始Docker
一.云计算的概念 PaaS(Platform-as-a-Service:平台即服务),把应用服务的运行和开发环境作为一种服务.SaaS(Software-as-a-Service),意思为软件即服务, ...
- Activiti Service介绍
原文地址:https://www.cnblogs.com/lyh421/p/6419518.html 第一章 认识Activiti 内容概览:讲解activiti的特点.接口概览.架构等基本信息. 1 ...
- 简述 高性能Linux服务器 模型架构 设计
主要从三个方面进行分析: 1.事件处理模式 2.并发模式 一.事件处理模式 1.Reactoor模式 定义: 主线程只负责监听文件描述符上是否有事件发生,有的话立即将该事件通知工作线程,除此之外,主线 ...
- 安装cnpm出现问题
安装cnpm: 命令行中输入 npm install -g cnpm --registry=http://registry.npm.taobao.org 报:cnpm不是内部命令 解决方法:设置环 ...