Spring AOP @Aspect support annotation

9 篇文章 0 订阅
  1. 还是这个例子,我们用完全annotation的方法来实现。代码我就不重复了,跟前面XML配置是同一套。

  2. 修改配置文件:

    <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-2.5.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

     

        <!-- Configure Target Objects -->

        <bean id="zoo" class="com.edi.poc.Zoo">

            <constructor-arg value="People"/>

        </bean>

        <bean id="dinoHall" class="com.edi.poc.DinoHall"/>

        <bean id="jack" class="com.edi.poc.Tourer">

            <constructor-arg value="Jack"/>

        </bean>

        <bean id="myAspect" class="com.edi.poc.aop.MyAspect"/>

     

        <aop:aspectj-autoproxy/>

    </beans>

  3. 修改Aspect

    @Aspect

    public class MyAspect {

     

    @Before("execution(* com.edi.poc.Zoo.enter(..))")

    public void before(JoinPoint joinPoint)

    {

    System.out.println("Before method...");

    Statistic.increaseTotalTraffic();

    }

     

    @After("execution(* com.edi.poc.ifc.Hall.visit(..))")

    public void after(JoinPoint joinPoint)

    {

    System.out.println("After return...");

    Statistic.increaseIncome(HALL_NAME.DINOSAUR, BigDecimal.valueOf(2l));

    }

    }

  4. 运行,输出为:

    Dinosaur hall is opened.

    The People Zoo is opened.

    Before method...

    Charge Jack $1.00 for ticket.

    Jack needs to be charged first.

    Dianosaur hall charges Jack $2.00

    Jack visited diano hall.

    After return...

    Current traffic: 1

    Income of DINOSAUR: ¥2.00

    Dinosaur hall is closed.

    The People Zoo is closed.

     

    一模一样。而且更加简单了。世界如此美好~如此清净……

     

  5. 可以看到用annotation来做AOP,实在是简单的不得了。这里唯一没有摆脱XML的,就是Spring的容器的配置文件。当然,Spring这段配置也可以完全用annotation来做,这样就完全不要applicationContext.xml这个文件了。参考如下步骤:
    1. 先把Main类改改,让它支持配置

    @ComponentScan

    @Configuration

    @EnableAspectJAutoProxy

    public class Main {

    ….

    }

    这里@ComponentScan是为了让Spring自动识别

    @Configuration是让该类变成配置类

    @EnableAspectJAutoProxy是启动AutoProxy

    1. 将几个让Spring自己加载的类变成ComponentSpring可以自动识别加载

    @Component

    public class Zoo {}

     

    @Component

    public class DinoHall implements Hall { … }

     

    @Aspect

    @Component

    public class MyAspect { … }

    如果不想让Spring来管理,可以在原类里面把@Component去掉,然后在Main类里面加上

    public class Main {

    @Bean(name="dinoHall")

    public Hall getDinoHall()

    {

    return new DinoHall();

    }

    }

    这样就可以通过ctx.getBean("dinoHall") 来获得实例。

    1. 最终修改调用过程如下:

    public static void main(String[] args) {

    ApplicationContext ctx = new AnnotationConfigApplicationContext(Main.class);

    Zoo zoo = (Zoo) ctx.getBean(Zoo.class);

    zoo.init("People");

    Hall dinoHall = (Hall)ctx.getBean("dinoHall");

    zoo.addHall(HALL_NAME.DINOSAUR, dinoHall);

    Tourer jack = new Tourer("Jack");

    zoo.open();

    jack.visit(zoo, HALL_NAME.DINOSAUR);

    System.out.println("Current traffic: " + Statistic.getTotalTraffic());

    NumberFormat currency = NumberFormat.getCurrencyInstance();

    System.out.println("Income of " + HALL_NAME.DINOSAUR + ": "+ currency.format(Statistic.getIncome(HALL_NAME.DINOSAUR)));

    zoo.close();

    }

    输出:

    Dinosaur hall is opened.

    The People Zoo is opened.

    Before method...

    Charge Jack $1.00 for ticket.

    Jack needs to be charged first.

    Dianosaur hall charges Jack $2.00

    Jack visited diano hall.

    After return...

    Current traffic: 1

    Income of DINOSAUR: ¥2.00

    Dinosaur hall is closed.

    The People Zoo is closed.

     

    1. 总结

    完全的annotation是非常方便的,就像ejb。但是,Springannotation做的还不是非常的完善,有些地方还需要提高。例如,在

    Hall dinoHall = (Hall)ctx.getBean("dinoHall");

    这里,我们如果不定义

    @Bean(name="dinoHall")

    public Hall getDinoHall()

    {

    return new DinoHall();

    }

    DinoHall上加上@Component后,用

    Hall dinoHall = (Hall)ctx.getBean(Hall.class);

    来获得实例,这里有个问题就是,后面传参的class,如果该类实现了接口,必须得传入其接口才行,否则就会报异常:

     org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.edi.poc.DinoHall] is defined

    这个我怀疑是因为Spring的容器智能的选择了JDK的动态代理来反射生成实际类,而JDK的动态代理要求Target必须实现接口。理论上改成强制CGLIB应该能解决问题,但是我找了下,并没找到如何用annotation来标示强制使用CGLIB……

     

    还例如,Spring3现在支持JSR-250定义的@PostConsturct等生命周期管理的注解,但是,我也没有找到如何使用annotation来启用。网上和官方文档都是给出了修改配置文件来使其支持。

     

    本文源码:

    https://github.com/EdisonXu/POC/tree/master/intro-aop

     

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@Aspect is an annotation in Spring that is used to define an aspect, which is a modularization of a concern that cuts across multiple classes. Aspects are used to encapsulate cross-cutting functionalities, such as logging, security, transaction management, and error handling, and apply them to multiple classes in a consistent and reusable manner. To use @Aspect, you need to define an aspect class that contains advice and pointcut expressions. The advice defines the action to be taken when a particular pointcut expression is matched, while the pointcut expression defines the set of join points where the advice should be applied. Here is an example of an aspect class that logs the execution of a method: ``` @Aspect public class LoggingAspect { @Before("execution(* com.example.MyService.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Method " + joinPoint.getSignature().getName() + " is about to be executed..."); } @AfterReturning("execution(* com.example.MyService.*(..))") public void logAfterReturning(JoinPoint joinPoint) { System.out.println("Method " + joinPoint.getSignature().getName() + " has been executed successfully."); } @AfterThrowing("execution(* com.example.MyService.*(..))") public void logAfterThrowing(JoinPoint joinPoint) { System.out.println("Method " + joinPoint.getSignature().getName() + " has thrown an exception."); } } ``` In this example, the aspect class logs the execution of any method in the com.example.MyService class. The @Before advice is executed before the method is executed, the @AfterReturning advice is executed after the method has returned successfully, and the @AfterThrowing advice is executed after the method has thrown an exception. To enable the aspect in your Spring application, you need to add the @EnableAspectJAutoProxy annotation to your configuration class. This annotation enables Spring's aspect-oriented programming (AOP) support and allows the framework to create proxies for the classes that match the pointcut expressions defined in the aspect. ``` @Configuration @EnableAspectJAutoProxy public class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } @Bean public LoggingAspect loggingAspect() { return new LoggingAspect(); } } ``` In this example, the AppConfig class defines a bean for the MyService interface and its implementation, as well as a bean for the LoggingAspect class. The @EnableAspectJAutoProxy annotation enables AOP support in the application context and allows Spring to intercept calls to the MyService bean and apply the logging aspect to it.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值