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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值