AOP
系统功能是公共的,在很多地方都会出现的功能,例如打印日志,性能监控,事务管理,安全验证等等,把需要某个系统的功能的方法看成一个切面。
典型的场景比如“开启事务,数据处理,提交事务”。这些重复的代码大多是所谓的权限管理、日志登陆、事务管理等必需却又污染着业务逻辑代码的内容,我们自然希望将它们提取出来,还业务逻辑一个清新的世界。
一些名词
连接点joinpoint:需要加入功能的位置
切入点pointcut:执行加入功能的连接点
通知advice:需要实现的功能
切面aspect:java中将切入点和通知等组合在一起的代码单元
Target:要操作的对象
织入weave:将功能加入到切入点的过程
流程
1)编写一个service类
2)编写一个通知类,实现MethodBeforeAdvice接口(三个参数,method方法,args方法的参数,target所在方法的对象)
3)配置切点 配置属性service的方法
4)配置切面
通知类型
前置通知:methodbeforeadvice在方法前
后置通知:afterRunning advice在方法后
环绕通知:methodInterceptor
异常通知:ThrowsAdvice在出现异常时
最终通知:在finally执行时 after
编写
需要在pom.xml加入aspectjweave依赖
public class Internal implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Object[] args = methodInvocation.getArguments();
if(!Arrays.asList(args).contains("abc123")){
System.out.println("非法合法"+methodInvocation.getMethod().getName());
return null;
}else{
System.out.println("参数合法");
}
System.out.println(methodInvocation.getStaticPart());
return "你好" ;
}
}
//对象
<bean id="springsop" class="com.woniu.spring.dao.springsop"/>
//定义通知
<bean id="Internal" class="com.woniu.spring.aop.Internal"/>
//定义切入点
<bean id="pointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value="com.woniu.spring.dao.springsop.prints"></property>
//给pattern属性赋值
</bean>
//组合切面
<bean id="aspect" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="pointCut" />
<property name="advice" ref="Internal"/>
</bean>
//包装
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
以上传统配置xml太过于繁琐下面介绍一个较为简单的方法
<!--对象-->
<bean id="springsop" class="com.woniu.spring.dao.springsop"/>
<!--通知-->
<bean id="txAdvice" class="com.woniu.spring.aop.TransactionArtive"/>
<aop:config>
<aop:aspect ref="txAdvice">
<!--切入点-->
<aop:pointcut id="daoPointCut" expression="execution(* com.woniu.spring.dao.*.*(..))"/>
<!--通知-->
<!--开始--> <aop:before method="start" pointcut-ref="daoPointCut"/>
<!--正常--> <aop:after-returning method="commit" pointcut-ref="daoPointCut"/>
<!--回滚--><aop:after-throwing method="rollback" pointcut-ref="daoPointCut"/>
</aop:aspect>
</aop:config>
以上用aop标签需要用到上文所说的依赖,所以必须在有依赖的情况下才能使用
还是过于繁琐怎么办?当然有更好的办法上一篇文章中提到过用java注解配置IOC,那么我们是不是也可以用java注解的方式,请看下一段代码
@Aspect
@Component
public class Tswin {
@Pointcut("execution(* com.woniu.spring.dao.*.*(..))")
public void userDao() { }
@Around("userDao()")
public Object invoke(ProceedingJoinPoint pjp) {
Object[] args = pjp.getArgs();
Object result = null;
try {
System.out.println("开启。。。");
result = pjp.proceed(args);
System.out.println("结束。。。。");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("回滚。。。");
}
return result;
}
}
这时就是通过注解来配置而xml只需要
<context:component-scan base-package="com.woniu.spring"/>
<aop:aspectj-autoproxy/>
这么简简单单二句就可以了
这还不是最简单的,接下来说下最简单的纯java配置
@Configuration
@ComponentScan("com.woniu.spring")
@EnableAspectJAutoProxy
public class Demi {
}
接下来就给类方法这些加上注解即可,会自动扫描到@Aspect 切面并应用
注解
@EnableAspectJAutoProxy == aop:aspectj-autoproxy这两句话作用是一样的
@Pointcut切入点 execution(* com.woniu.spring.dao..(…))" 也要填入这句话
@Around通知
@Aspect声明切面