年轻人,我观你骨骼精奇,定是万里无一的练武奇才,老夫这里有一本失传已久的武林秘籍,现赠于你,望你勤加苦练,早日修成正果...
AOP(面向切面编程):Aspect Oriented Programming
第一式、使用切面编程需要的配置<aop:aspectj-autoproxy expose-proxy="true" />
开启切面编程功能,需要在applicationContext.xml文件中配置。
作用是:声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,植入切面
- @Aspect
放在类头上,把这个类作为一个切面即声明一个切面 -
@Pointcut
放在方法头上,定义一个可被别的方法引用的切入点表达式。
Pointcut是Join Point(连接点)的集合,即它是程序中需要注入Advice(切入点上执行的行为)的位置的集合,指明Advice要在什么样的条件下才能被触发。- 2.1、Pointcut表达式定义:Pointcut 是指哪些方法需要被执行"AOP",是由"Pointcut Expression"来描述的。 Pointcut可以有下列方式来定义或者通过&& || 和!的方式进行组合。
args()
execution()
this()
target()
within()
annotation - 2.2、Pointcut表达式的格式:其中execution 是用的最多的,其格式为:execution(方法操作权限?返回值?方法所在包?方法名(参数)异常?),其中返回值,方法名和参数是必须的。
-
常用Pointcut表达式的讲解:execution( com.glodon.gcxx.dao.hibimpl..(..)) ,这是com.glodon.gcxx.dao.hibimpl 包下所有的类的所有方法。
第一个代表所有的返回值类型 ,第二个代表所有的类, 第三个代表类所有方法 ,最后一个..代表所有的参数。
下面给出一些常见切入点表达式的例子。1.任意公共方法的执行:execution(public * *(..)) 2.任何一个以“set”开始的方法的执行:execution(* set*(..)) 3.AccountService 接口的任意方法的执行:execution(* com.xyz.service.AccountService.*(..)) 4.定义在service包里的任意方法的执行:execution(* com.xyz.service.*.*(..)) 5.定义在service包或者子包里的任意类的任意方法的执行:execution(* com.xyz.service..*.*(..))
- Pointcut 可以通过Java注解和XML两种方式配置,如下所示
<aop:config> <aop:aspectrefaop:aspectref="aspectDef"> <aop:pointcutidaop:pointcutid="pointcut1"expression="execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))"/> <aop:before pointcut-ref="pointcut1" method="beforeAdvice" /> </aop:aspect> </aop:config>
- 2.1、Pointcut表达式定义:Pointcut 是指哪些方法需要被执行"AOP",是由"Pointcut Expression"来描述的。 Pointcut可以有下列方式来定义或者通过&& || 和!的方式进行组合。
@Component
@Aspect
public class AspectDef {
//@Pointcut("execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")
//@Pointcut("within(com.test.spring.aop.pointcutexp..*)")
//@Pointcut("this(com.test.spring.aop.pointcutexp.Intf)")
//@Pointcut("target(com.test.spring.aop.pointcutexp.Intf)")
//@Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
//@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
@Pointcut("args(String)")
public void pointcut1() {
}
@Before(value = "pointcut1()")
public void beforeAdvice() {
System.out.println("pointcut1 @Before...");
}
- 3、advice
5种通知:advice。
3.1、@Before,前置通知,放在方法头上。
3.2、@After,后置【finally】通知,放在方法头上。
3.3、@AfterReturning,后置【try】通知,放在方法头上,使用returning来引用方法返回值。
3.4、@AfterThrowing,后置【catch】通知,放在方法头上,使用throwing来引用抛出的异常。
3.5、@Around,环绕通知,放在方法头上,这个方法要决定真实的方法是否执行,而且必须有返回值。
- 权限控制
- 日志
- 事务等等
首先在applicationContext.xml配置中配置:<aop:aspectj-autoproxy expose-proxy="true" />
1、使用execution定义pointcut方式
- 定义切面
/**
* 通过aop拦截后执行具体操作
* @author huangqw
* */
@Aspect
@Component
public class LogIntercept {
// com.glodon.action包下任意公共的(public)方法————解析切入点:public表示操作方法的权限,第一个*表示返回值,com.glodon.action表示报名,..表示子包,第二个*表示类,第三个*表示方法名称,(..)表示参数
@Pointcut(value="execution(public * com.glodon.action..*.*(..))")
public void writeLog() {
}
<br>// 前置拦截,在执行目标方法之前的操作
@Before("writeLog()")
public void before() {
this.printLog("@Before 方法执行前——————做日志");
}
// 环绕拦截,在执行目标方法的前后的操作
@Around("writeLog()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
this.printLog("@Around 方法执行前——————做日志");
pjp.proceed();
this.printLog("@Around 方法执行后——————做日志");
}
// 后置拦截,在执行目标方法之前的操作
@After("writeLog()")
public void after() {
this.printLog("@After 方法执行后——————做日志");
}
private void printLog(String str) {
System.out.println(str);
}
}
- 使用切面
/**
* aop测试类
* @author huangqw
*/
@Controller
public class TestAction {
public void query() {
System.out.println("查询操作");
}
public static void main(String[] args) {
@SuppressWarnings("resource")
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("resources/applicationContext.xml");
TestAction testAction = (TestAction) ctx.getBean("testAction");
testAction.query();
ctx.destroy();
}
}
- 执行结果
2、使用注解定义pointcut方式 - 定义注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AroundTest {
String name() default "测试哈";
}
- 定义切面
@Component
@Aspect
public class AroundTestInteceptor {
public AroundTestInteceptor(){
}
/**
* 定义切入点
*/
@Pointcut(value="@annotation(com.glodon.around.AroundTest)")
public void logAnnotatedMethod() {
}
/**
* 拦截方法
* @param pjp
* @return
* @throws Throwable
*/
@Around("logAnnotatedMethod()")
public Object inteceptorAction(ProceedingJoinPoint pjp) throws Throwable {
Object o = null;
MethodSignature joinPointObject = (MethodSignature) pjp.getSignature();
Method method = joinPointObject.getMethod();
boolean flag = method.isAnnotationPresent(AroundTest.class) ;
if (flag) {
AroundTest annotation = method.getAnnotation(AroundTest.class);
Date enterDate = new Date();
System.out.println("开始执行方法:" + annotation.name());
//用于执行委托对象的目标方法
o = pjp.proceed();
Date leaveDate = new Date();
System.out.println("结束执行方法:"+ annotation.name() +",方法执行的时间:" + (leaveDate.getTime() - enterDate.getTime()));
}
return o;
}
}
- 使用切面
/**
* aop测试类
* @author huangqw
*/
@Controller
public class TestAction {
@AroundTest(name="ceshi")
public void query() {
System.out.println("查询操作");
}
public static void main(String[] args) {
@SuppressWarnings("resource")
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("resources/applicationContext.xml");
TestAction testAction = (TestAction) ctx.getBean("testAction");
testAction.query();
ctx.destroy();
}
}
- 执行结果
.
.
.
.
.
.
年轻人,老夫已将所有功力传授与你,望你勤加苦练...阿弥陀佛
点击查看更多内容
7人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦