spring-aop学习【基于注解】
我个人觉得,这个好像就是用在定制日志输出上,和log4j很像。
用途:
如果业务方法调用每一步都需要详细的日志,那就用这个吧
好处就是:
方便维护,只包含业务代码
下面开始说明:
所需要的jar包:
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.1.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
直接上代码:
声明一个接口
package com.spring.bean.aop; import java.util.List; /**
*
* @author Administrator
*
*/
public interface UserService {
// 打招呼
void say();
// 获取年龄
int getValue(List<Integer> array,int index);
}
这是接口的实现类
package com.spring.bean.aop; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; /**
*
* @author Administrator
* 实现类
*/
@Service("userService")
public class UserServiceImpl implements UserService { /**
* 自动装配use对象
*/
@Autowired
private User user;
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("我叫"+user.getName()+",今年"+user.getAge()+"岁,你好!!");
} @Override
public int getValue(List<Integer> array, int index) {
// TODO Auto-generated method stub
return array.get(index);
} }
用户对象信息
package com.spring.bean.aop; import org.springframework.stereotype.Component; /**
* @author Administrator
* 用户信息
*/
@Component
public class User { String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
然后是两个切面代码
package com.spring.bean.aop; import java.util.Arrays; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; /**
* 声明一个切面
* @author Administrator
*
*/
//order可以指定哪个切面先执行,数值越小,优先执行
@Order(1)
@Aspect
@Component
public class MyLoggingAspectj { // 声明一个切入点
@Pointcut("execution(* *(..))")
public void pointcut(){ } /**
* 前置通知,该方法执行在被调用方法之前
* @param joinPoint
*/
@Before("pointcut())")
public void beforeMethod(JoinPoint joinPoint){
// 获得调用的方法名
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("MyLoggingAspectj the method "+methodName+"begins with "+Arrays.asList(args));
} }
第二个切面代码
package com.spring.bean.aop; import java.util.Arrays; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; /**
* 声明一个切面
* @author Administrator
*
*/
@Order(2)
@Aspect
@Component
public class LoggingAspectj { // 声明一个切入点
@Pointcut("execution(* *(..))")
public void pointcut(){ } /* *//**
* 前置通知,该方法执行在被调用方法之前
* @param joinPoint
*//*
@Before("pointcut())")
public void beforeMethod(JoinPoint joinPoint){
// 获得调用的方法名
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("the method "+methodName+"begins with "+Arrays.asList(args));
} *//**
* 后置通知
* 该方法执行在被调用方法之后,报错也依然执行
* @param joinPoint
*//*
@After("pointcut())")
public void afterMethod(JoinPoint joinPoint){
// 获得调用的方法名
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("the method "+methodName+"Ends with "+Arrays.asList(args));
} *//**
* 返回通知, 在方法返回结果之后执行,异常无返回值
* @param joinPoint
*//*
@AfterReturning(value="pointcut())",returning="result")
public void afterReturning(JoinPoint joinPoint,Object result){
// 获得调用的方法名
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("the method "+methodName+"afterReturning with "+Arrays.asList(args)+" ["+result+"]");
} *//**
* 异常通知
* 在方法抛出异常之后
* @param joinPoint
*//*
@AfterThrowing(value="pointcut()",throwing="e")
public void afterReturning(JoinPoint joinPoint,Exception e){
// 获得调用的方法名
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("the method "+methodName+"afterThrowing with "+Arrays.asList(args)+e);
}*/ /**
* 环绕通知需要配合ProceedingJoinPoint使用,相当于动态代理
* @param pjp
* @return
*/
@Around(value="pointcut()")
public Object aroundMethod(ProceedingJoinPoint pjp) {
// 获得调用的方法名
String methodName = pjp.getSignature().getName();
Object result = null;
// 调用目标方法
try {
// 前置通知
System.out.println("the method " + methodName + "Begins with " + Arrays.asList(pjp.getArgs()));
result = pjp.proceed();
// 后置通知
System.out.println("the method " + methodName + "Ends with " + Arrays.asList(pjp.getArgs()));
// 后置有返回值
System.out.println(
"the method " + methodName + "Ends with " + Arrays.asList(pjp.getArgs()) + " [" + result + "]");
} catch (Throwable e) {
// TODO Auto-generated catch block
// 异常通知
System.out.println("the method " + methodName + "AfterThrowing with " + Arrays.asList(pjp.getArgs()) + e);
// e.printStackTrace();
// 不加这句,会报错,因为result返回值为null
throw new RuntimeException(e);
}
System.out.println("the method " + methodName + "LastEnds with " + Arrays.asList(pjp.getArgs()));
return result;
} }
测试代码:
package com.spring.bean.aop; import java.util.ArrayList;
import java.util.List; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ctx=new ClassPathXmlApplicationContext("bean-aop.xml");
UserService userServiceImpl=(UserService) ctx.getBean("userService");
User user=(User) ctx.getBean("user");
List<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
int age = userServiceImpl.getValue(arrayList, 1);
user.setName("xiaoqiang");
user.setAge(age);
userServiceImpl.say();
} }
bean文件
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 自动扫描的包 -->
<context:component-scan base-package="com.spring.bean.aop"></context:component-scan>
<!-- 使 AspectJ 的注解起作用 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
总结:
1.在pom文件添加依赖,在 Spring 的配置文件中加入 aop 的命名空间。
<!--使用AspectJ方式注解需要相应的包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!--使用AspectJ方式注解需要相应的包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
2.为接口实现类添加注解@Component
3.编写一个切面类,配置切面
* 3.1 在配置文件中配置自动扫描的包: <context:component-scan base-package="com.spring.bean.aop"></context:component-scan>
* 3.2 加入使 AspjectJ 注解起作用的配置: <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
* 为匹配的类自动生成动态代理对象.
4.编写前置通知方法,在方法上方添加注解
// 表达式注意格式: 修饰 +方法(有无返回)+包名+类名+方法名+参数
@Before("execution(public int com.spring.bean.annotation.aopimpl.Calculation.sub(int, int))")
* @Before 表示在目标方法执行之前执行 @Before 标记的方法的方法体.
* @Before 里面的是切入点表达式:
如关注详细参数,添加joinpoint对象,可以访问到方法的签名和参数
spring-aop学习【基于注解】的更多相关文章
- SSM框架—Spring AOP之基于注解的声明式AspectJ(Demo)
项目结构 XML <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http ...
- Spring AOP 学习例子
http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example 工作忙,时间紧,不过事情再多,学习是必须的.记得以前的部门老大 ...
- 在Intellij上面导入项目 & AOP示例项目 & AspectJ学习 & Spring AoP学习
为了学习这篇文章里面下载的代码:http://www.cnblogs.com/charlesblc/p/6083687.html 需要用Intellij导入一个已有工程.源文件原始内容也可见:link ...
- 运用Spring Aop,一个注解实现日志记录
运用Spring Aop,一个注解实现日志记录 1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到 ...
- 使用 Spring 2.5 基于注解驱动的 Spring MVC
http://www.ibm.com/developerworks/cn/java/j-lo-spring25-mvc/ 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Sp ...
- 使用 Spring 2.5 基于注解驱动的 Spring MVC--转
概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Spring 2.5 又为 Spring MVC 引入了注解驱动功能.现在你无须让 Controller 继承任何接口,无需在 ...
- Spring框架学习之注解配置与AOP思想
上篇我们介绍了Spring中有关高级依赖关系配置的内容,也可以调用任意方法的返回值作为属性注入的值,它解决了Spring配置文件的动态性不足的缺点.而本篇,我们将介绍Spring的又一大核心 ...
- 一步一步深入spring(5)--使用基于注解的spring实现 AOP
1.要利用spring aop,至少需要添加以下jar包 使用spring需要的jarspring.jar .commons-logging.jar 使用切面编程(AOP)需要的jar aspectj ...
- spring aop学习记录
许多AOP框架,比较常用的是Spring AOP 与AspectJ.这里主要学习的Spring AOP. 关于AOP 日志.事务.安全验证这些通用的.散步在系统各处的需要在实现业务逻辑时关注的事情称为 ...
- AOP和spring AOP学习记录
AOP基本概念的理解 面向切面AOP主要是在编译期或运行时,对程序进行织入,实现代理, 对原代码毫无侵入性,不破坏主要业务逻辑,减少程序的耦合度. 主要应用范围: 日志记录,性能统计,安全控制,事务处 ...
随机推荐
- AD域控制器通过组策略禁止USB设备
问题:域环境下如何禁用USB口设备? 第一种:用传统的办法,在Bios中禁用USB. 第二种: 微软技术支持回答:根据您的需求, Windows识别USB设备主要通过两个文件,一个是Usbstor.p ...
- 11i和R12配置JAR包
R11:$IAS_ORACLE_HOME/Apache/Jserv/etc/jserv.properties R12: 方法1:直接解压JAR包放到$JAVA_TOP下: 方法2:编辑:$ORA_CO ...
- 操作系统中的P,V操作(转)
无论是计算机考研.计算机软件水平考试.计算机操作系统期末考试还是其他计算机岗位考试,P.V原语操作都是一个常考点.下面笔者总结了关于P.V操作的一些知识. 信号量是最早出现的用来解决进程同步与互斥问题 ...
- jquery easyui datagrid翻页后再查询始终从第一页开始
在查询之前将datagrid的属性pageNumber重新设置为1 var opts = grid.datagrid('options'); opts.pageNumber = 1; easyui d ...
- js的DOM的方法和属性总结
1.DOM的获取元素document.getElementById()context.getElementsByTagName(tag) (可以获取相应上下文环境所有的tag标签)context.ge ...
- 小明的密码-初级DP解法
#include #include #include using namespace std; int visited[5][20][9009];// 访问情况 int dp[5][20][9009] ...
- javaScript数据类型及判断
ECMAScript数据类型概念: ECMAScript数据类型分为两类:原始类型和对象类型(即基本类型和引用类型): ECMAScript数据类型也可以分为可变类型和不可变类型,数组和对象属于可变类 ...
- ajax获取json数据 for select2
json数据“a.json” [ { "id": "1", "text": "张三" }, { "id&quo ...
- toast组件小结
简介:toast是"吐司"的意思,它属于android杂项组件,是一个简单的消息提示框,类似于javascript中的alert. 作用 显示文本 显示图片 显示图文 3.常用方法 ...
- mysql 性能优化方向
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...