AOP也就是面向切面编程一向与IOC被称为是Spring的两大特性。作为依赖注入的补充,AOP使得我们能将每个方法都要调用的方法抽离出来形成一个单独的模块,降低了代码的耦合性,也降低了管理代码的难度。
注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。作为JAVA WEB开发者,我们每天每一个方法都大量的使用了注解。但是正如上文所说,单纯的注解并没有任何作用,只能用来生成文档、标识功能。
如果我们需要自定义一个注解,并且保证自定义的这个注解能发生作用,能改变我们的代码效果。那么我们就需要使用反射来追踪方法,处理这个注解,为他提供配套的操作。当然反射的使用的是非常麻烦的,而且在使用Spring进行开发时,已经提供了AOP这一工具使得我们可以为自定义注解提供配套的切面类,高效率低耦合的使用自定义注解。
我们可以使用Spring AOP提供的@Pointcut标签轻松的获取所有需要处理的自定义注解类及方法,随后可以通过@Before,@After的方法为所有标记了该注解的类或类中的方法添加一层前置方法或者后置方法。以下是3个用于追踪注解的@PointCut表达式:
1.@annotation 表示所有实现了注解的方法
2.@target 表示所有实现了注解的对象中的方法
3.@within 表示所有实现了注解的类中的方法
比较典型的基于自定义注解及AOP的实践就是 基于AOP的spring多数据源配置了,有一个非常不错的文档,提供一下可以参考基于AOP的spring多数据源配置。
然后这个文档中的方法是配置到method级别的,实际使用中还是要每个方法都加注解,省点事的话可以配到类级别,这样又省了一点时间不是,方法如下:
@Aspect
@Component
@Order(1)
public class DynamicDataSourceAspect {
@Before("@within(com.ucmed.util.dataSource.DynamicDataSourceAnnotation)") //前置通知
public void simpleBefore(JoinPoint point){
//获得当前访问的class
Class<?> className = point.getTarget().getClass();
DynamicDataSourceAnnotation dataSourceAnnotation = className.getAnnotation(DynamicDataSourceAnnotation.class);
if (dataSourceAnnotation != null ) {
//获得访问的方法名
String methodName = point.getSignature().getName();
//得到方法的参数的类型
Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
String dataSource = dataSourceAnnotation.dataSource();
try {
Method method = className.getMethod(methodName, argClass);
if (method.isAnnotationPresent(DynamicDataSourceAnnotation.class)) {
DynamicDataSourceAnnotation annotation = method.getAnnotation(DynamicDataSourceAnnotation.class);
dataSource = annotation.dataSource();
System.out.println("DataSource Aop ====> "+dataSource);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DynamicDataSourceHolder.setDataSource(dataSource);
}
}
@After("@annotation(com.ucmed.util.dataSource.DynamicDataSourceAnnotation)") //后置通知
public void simpleAfter(JoinPoint point){
//获得当前访问的class
Class<?> className = point.getTarget().getClass();
DynamicDataSourceAnnotation dataSourceAnnotation = className.getAnnotation(DynamicDataSourceAnnotation.class);
if (dataSourceAnnotation != null ) {
//获得访问的方法名
String methodName = point.getSignature().getName();
//得到方法的参数的类型
Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
String dataSource = dataSourceAnnotation.dataSource();
try {
Method method = className.getMethod(methodName, argClass);
if (method.isAnnotationPresent(DynamicDataSourceAnnotation.class)) {
DynamicDataSourceAnnotation annotation = method.getAnnotation(DynamicDataSourceAnnotation.class);
dataSource = annotation.dataSource();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(dataSource != null && !DynamicDataSourceHolder.MY_DATA_SOURCE.equals(dataSource)) DynamicDataSourceHolder.clearDataSource();
}
}
}