栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

武林秘籍之Spring AOP 切面编程的简单应用

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

武林秘籍之Spring AOP 切面编程的简单应用


年轻人,我观你骨骼精奇,定是万里无一的练武奇才,老夫这里有一本失传已久的武林秘籍,现赠于你,望你勤加苦练,早日修成正果...

AOP(面向切面编程):Aspect Oriented Programming

第一式、使用切面编程需要的配置

  开启切面编程功能,需要在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两种方式配置,如下所示
      
      
      
      
      
@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,环绕通知,放在方法头上,这个方法要决定真实的方法是否执行,而且必须有返回值。
第三式:主要应用场景
  1. 权限控制
  2. 日志
  3. 事务等等
第四式:例子

首先在applicationContext.xml配置中配置:
1、使用execution定义pointcut方式

  • 定义切面
@Aspect
@Component
public class LogIntercept {

//  com.glodon.action包下任意公共的(public)方法————解析切入点:public表示操作方法的权限,第一个*表示返回值,com.glodon.action表示报名,..表示子包,第二个*表示类,第三个*表示方法名称,(..)表示参数
    @Pointcut(value="execution(public * com.glodon.action..*.*(..))")
    public void writeLog() {
    }
    
//   前置拦截,在执行目标方法之前的操作 @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); } }
  • 使用切面
@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() {
    }

    
    @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;
    }
}
  • 使用切面
@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();
    }
}
  • 执行结果

    .
    .
    .
    .
    .
    .
    年轻人,老夫已将所有功力传授与你,望你勤加苦练...阿弥陀佛
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/233806.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号