您的位置:首页 > 编程语言 > ASP

Spring AOP @Aspect support annotation

2013-10-30 09:08 309 查看
还是这个例子,我们用完全annotation的方法来实现。代码我就不重复了,跟前面XML配置是同一套。
修改配置文件:

<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>
修改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));

}
}
运行,输出为:
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.

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

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

先把Main类改改,让它支持配置

@ComponentScan
@Configuration
@EnableAspectJAutoProxy
public class Main {

….
}
这里@ComponentScan是为了让Spring自动识别
@Configuration是让该类变成配置类
@EnableAspectJAutoProxy是启动AutoProxy

将几个让Spring自己加载的类变成Component,Spring可以自动识别加载

@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")
来获得实例。

最终修改调用过程如下:

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.

总结

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

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: