在Spring中使用AspectJ实现AOP

在Spring中,最常用的AOP框架是AspectJ,使用AspectJ实现AOP有2种方式:

  • 基于XML的声明式AspectJ
  • 基于注解的声明式AspectJ

基于XML的声明式AspectJ

1、在项目中添加包spring-aspects.jar(spring自带)、aspectjweaver.jar(需要自己下载添加)

2、新建包user,包下新建类User

1 public class User{
2     public void addUser(){
3         System.out.println("正在添加用户");
4         System.out.println("添加用户成功");
5     }
6 }

User可实现接口。

3、新建包my_aspect,包下新建切面类MyAspect。注意是新建Class,不是新建Aspect。

 1 public class MyAspect {
 2     //前置通知
 3     public void myBefore(){
 4         System.out.println("正在检查权限");
 5         System.out.println("权限已够");
 6     }
 7
 8     //后置通知
 9     public void myAfterReturning(){
10         System.out.println("正在记录日志");
11         System.out.println("日志记录完毕");
12     }
13
14     //环绕通知,同时在前后增强。
15     public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
16         myBefore();
17         Object object=proceedingJoinPoint.proceed();
18         myAfterReturning();
19         return object;
20     }
21
22     //异常通知
23     public void myAfterThrowing(Throwable e){
24         System.out.println("出错了:"+e.getMessage());
25     }
26
27     //最终通知
28     public void myAfter(){
29         System.out.println("正在释放资源");
30         System.out.println("资源释放完毕");
31     }
32 }

根据需要,写通知。函数名是自定义的,但不能使用aspectj的关键字。

可使用形参 JoinPoint joinPoint ,通过 joinPoint.getSignature().getName() 获取增强的方法名。

4、在xml中配置

<!--目标类-->
    <bean id="user" class="user.User" />

    <!--切面类-->
    <bean id="myAspect" class="my_aspect.MyAspect" />

    <!--AOP配置-->
    <aop:config>
        <!--配置切面,一个aspect配置一个切面-->
        <aop:aspect ref="myAspect">
            <!--配置全局切入点-->
            <aop:pointcut  id="myPointCut" expression="execution(* user.*.*(..))" />
            <!--配置要使用的通知-->
            <aop:before method="myBefore" pointcut-ref="myPointCut" />
            <aop:after-returning method="myAfterReturning" pointcut="execution(void user.User.addUser())" />
        </aop:aspect>
    </aop:config>

<aop:pointcut />配置的是全局切入点(所有通知都可引用),可在通知中使用pointcut-ref属性引用。也可以在单个通知中使用pointcut属性配置自己的切入点。

method属性指定这个通知对应的切面类中的方法。如果方法使用了参数JoinPoint(切入点),不用额外传参,pointcut/point-ref传递的就是切入点。

切入点指的就是目标方法。

  • 前置通知
    <aop:before method="myBefore" pointcut-ref="myPointCut" />
  • 后置通知
   <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" />

后置通知可使用returning属性指定指定一个参数,这个参数表示目标方法的返回值,会被传递给后置通知的方法。returning属性只有后置通知能使用。

  <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal" />
  • 环绕通知(前、后增强)
  <aop:around method="myAround" pointcut-ref="myPointCut" />

环绕方法的参数 ProceedingJoinPoint proceedingJoinPoint 是JoinPoint的子类,不用额外传参。

如果同时使用前置/后置通知、环绕通知,则先执行环绕前,再执行前置(如果有),执行目标方法,执行后置(如果有),然后执行环绕后。


  • 异常通知
    <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>

异常方法需要一个参数 Throwable e ,需要用throwing属性传递参数。

异常通知在目标方法发生异常、抛出异常时自动执行,throwing表示的就是目标方法抛出的异常。

目标方法发生异常时,会先执行异常方法,然后在控制台打印错误信息。

  • 最终通知
    <aop:after method="myAfter" pointcut-ref="myPointCut" />

最终通知是在目标方法执行后、后置方法执行后/环绕方法执行后(如果有),才执行的。

如果之前的代码(目标方法)发生异常或者被异常中止,后置通知以及环绕通知的后半部分是不会执行的。

最终通知,就算前面代码发生异常、被异常中止,也会执行,除非退出JVM。所以常在最终方法中做一些断开连接、关闭资源的操作。

5、新建包test,包下新建测试类Test

1 public class Test {
2     public static void main(String[] args) {
3         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
4         User user=applicationContext.getBean("user", User.class);
5         user.addUser();
6     }
7 }

基于注解的声明式AspectJ

基于代理类的AOP很繁琐,基于xml的声明式AspectJ便捷很多,但如果要配置的切面很多,xml文件会很臃肿。基于注解的声明式AspectJ可解决此问题。

基于注解的声明式AspectJ是最常用的,简便、xml文件也比较简洁。

1、在项目中添加包spring-aspects.jar(spring自带)、aspectjweaver.jar(需要自己下载添加)

2、新建包user,包下新建类User(可实现接口)

1 @Repository("user")
2 public class User{
3     public void addUser(){
4         System.out.println("正在添加用户");
5         System.out.println("添加用户成功");
6     }
7 }

原本要在xml中配置目标类的Bean,这里使用注解自动装配。@Repository("user")是Dao层的注解,因为添加用户一般要操作数据库,这里只是写了一个模拟。

我们显式指定Bean的id/name为user,其实@Repository默认id/name就是类名的camel写法。

3、新建包my_aspect,包下新建切面类MyAspect

 1 @Aspect
 2 @Component
 3 public class MyAspect {
 4     //全局切入点
 5     @Pointcut("execution(void user.User.*())")
 6     private void myPointCut(){}
 7
 8     //前置通知
 9     @Before("myPointCut()")
10     public void myBefore(){
11         System.out.println("正在检查权限");
12         System.out.println("权限已够");
13     }
14
15     //后置通知
16     @AfterReturning("execution(void user.User.*())")
17     public void myAfterReturning(){
18         System.out.println("正在记录日志");
19         System.out.println("日志记录完毕");
20     }
21
22     //环绕通知,同时在前后增强。
23     public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
24         myBefore();
25         Object object=proceedingJoinPoint.proceed();
26         myAfterReturning();
27         return object;
28     }
29
30     //异常通知
31     public void myAfterThrowing(Throwable e){
32         System.out.println("出错了:"+e.getMessage());
33     }
34
35     //最终通知
36     public void myAfter(){
37         System.out.println("正在释放资源");
38         System.out.println("资源释放完毕");
39
40     }
41 }

原本要在xm中配置切面Bean,这里使用@Aspect(使用aspectj配置,相当于<aop:congif>元素)、 @Component(配置为Bean,相当于<bean>元素)  2个注解配置。

需要使用注解把要使用的方法标注为对应的通知方法,需要指定切入点。

可先配置全局切入点:

    //全局切入点
    @Pointcut("execution(void user.User.*())")
    private void myPointCut(){}

然后在注解中通过   "方法名()"    引用:

    //前置通知
    @Before(value = "myPointCut()")

如果只配置切入点这一个参数,可简写:

    //前置通知
    @Before("myPointCut()")

也可以自行配置:

     //后置通知
    @AfterReturning("execution(void user.User.*())")

异常通知比较特殊,需要传递一个异常参数:

    //异常通知
    @AfterThrowing(value = "myPointCut()",throwing = "e")

只有使用了注解标注的方法才会作为通知自动调用。

其实就是把xml中的配置转换为相应的注解配置。

4、在xml中配置

    <!--启用Spring注解,指定使用了注解的包,有多个包时逗号分隔-->
    <context:component-scan base-package="user,my_aspect" />

    <!--启用AspectJ的注解-->
    <aop:aspectj-autoproxy />

5、新建包test,包下新建测试类Test

1 public class Test {
2     public static void main(String[] args) {
3         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
4         User user=applicationContext.getBean("user", User.class);
5         user.addUser();
6     }
7 }

原文地址:https://www.cnblogs.com/chy18883701161/p/11144903.html

时间: 2024-10-04 22:41:40

在Spring中使用AspectJ实现AOP的相关文章

Spring AOP报错处理 Can not set field to $Proxy 在spring中使用事物或AOP遇到的错误

[转] 解决方法: http://forum.springsource.org/showthread.php?85016-IllegalArgumentException-with-ApplicationContextAware-Proxy 在配置文件中加入proxy-target-class="true" <tx:annotation-driven transaction-manager="transactionManager" proxy-target-c

Spring中的IOC和AOP

一.IOC(DI) Inversion of Control 控制反转,也叫(Dependency Injection)依赖注入. 我们平常使用对象的时候,一般都是直接使用关键字类new一个对象,那这样有什么坏处呢?其实很显然的,使用new那么就表示当前模块已经不知不觉的和 new的对象耦合了,而我们通常都是更高层次的抽象模块调用底层的实现模块,这样也就产生了模块依赖于具体的实现,这样与我们JAVA中提倡的面向接口面向抽象编程是相冲突的,而且这样做也带来系统的模块架构问题. 很简单的例子,我们在

Spring基于注解@AspectJ的AOP

Spring除了支持XML方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明. 但是用注解方式需要在XML启用对@AspectJ的支持<aop:aspectj-autoproxy/>,将在Spring上下文创建一个AnnotationAwareAspectJAutoProxyCreator类,它会自动代理一些Bean,这些Bean的方法需要与使用@Aspect注解的Bena中所定义的切点相匹配,而这些切点又是使用@Pointcut注解定义出来的,下面来看下例子(PS:我的例子都

理解Spring中的IOC和AOP

我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式 IOC就是典型的工厂模式,通过sessionfactory去注入实例. AOP就是典型的代理模式的体现. 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关

对Spring中的IOC与AOP简单理解(简单的理解,通俗易懂)

IOC与AOP是Spring中的核心:IOC是控制反转,AOP是面向对象编程,IOC采用了工厂设计模式,AOP采用了代理设计模式. 一.IOC IOC是控制反转,而控制反转是一种思想,而DI是依赖注入,是IOC的实现,DI有构造注入.属性注入(设值注入)(基于注解的方式或者基于XML的方式).在项目程序中,频繁的去手动创建对象,new对象使得代码间耦合度太大,而Spring提供了容器,通俗的讲:你无需知道对象的创建过程,只需从其中拿到结果就可以了:把对象的创建以及各个对象间的关系还有对象的销毁交

javaEE之-------Spring中的aspectJ的应用

采用aspectJ可以且整个项目里面的需求. 如数据库的事物处理等 演示实例为主: 和之前一样,先采用java手动写的方式.. 切面技术 = 通知 + 切点 <span style="font-size:18px;">@Test public void test1(){ //1,获得代理工厂 ProxyFactory factory = new ProxyFactory(new Person()); //2,切点 AspectJExpressionPointcut cut

spring中面向切面编程(AOP)的个人理解

面向切面编程AOP,是spring的一大特点 Aspect切面:封装共性功能的(增强功能的)类 Advice通过:切面类中封装的增强功能的方法. PointCut:切入点,是一个集合的概念,该集合的表达使用一个正则表达式表达 所有核心业务对象的所有方法的前后(事务处理AOP典型的应用) JoinPoint:连接点,程序中需要加入advice的地方,而且正在执行的ponitCut 织入(Weaving):将aspect和核心业务对象,进行整合的过程. 通过特定接口实现AOp Aop通知的类型: B

spring中的ioc和aop概念

众所周知,现在最流行的三大框架就是Spring.Spring MVC和Mybatis.使用Spring,主要是方便了普通的程序员进行快速开发. 控制反转(IOC,Inversion Of Controll) 控制反转指的是对象创建责任的反转.原本我们需要创建一个对象必须要手动去new一个,那么在类中由于代码越来越多,需要管理的依赖和引用也会越来越多,代码维护的成本也会越来越高.Spring就把创建对象的控制权交给了IOC容器去完成. 举个例子,某一天你生病了,但是你不清楚自己到底得了什么病,你只

spring中使用动态代理(AOP)

spring是整合了BGLIB和JDK两种动态代理 示例:使用CGLIB代理 public class MyCar { private String color = "blue"; public void run() { System.out.println("我的汽车跑起来了" + color); } } 测试 public class SpringProxy { public static void main(String[] args) { //将代理类的cl