1、 在beans.xml的基本属性
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 打开Spring的Annotation -->
<context:annotation-config/>
<!-- 设定Spring去哪些包中找Annotation -->
<context:component-scan base-package="spring"/>
</beans>
2、在beans.xml打开AOP的自动检测
<!-- 打开基于Annotation的AOP -->
<aop:aspectj-autoproxy/>
3、创建一个需要实现动态代理的类
//实现代理的类
public class LogAspect {
public void logStart() {
Logger.info("加入日志");
}
}
//这个是功能类
public class Logger {
public static void info(String info) {
System.out.println("----" + info);
}
}
4、导入aspect包
Spring使用的是AspectJ包来实现AOP的,所以需要导入这个包
5、@Aspect注解声明
@Component("logAspect")
@Aspect //声明这个类是切面类
public class LogAspect {
public void logStart() {
Logger.info("加入日志");
}
}
6、在相应的要进行操作横切点上面加入PointCut的说明
@Component("logAspect")
@Aspect //声明这个类是切面类
public class LogAspect {
/**
* execution的写法
* 第一个‘*’表示任意返回值
* 第二个‘*’表示包中的所有类
* 第三个‘&’表示以Add开头的所有方法
* (..)表示任意参数
*/
@Before("execution("
+ "* " //返回值,为任何值
+ "spring.dao.*" //包名,包名下的所有类
+ ".add*" //方法名,以add开头的所有方法
+ "(..))" //方法的参数,两个句点表示任何参数
+ "||" //添加日志范围,用‘||’
+ "execution(* spring.dao.*.delete(..))")
public void logStart() {
Logger.info("加入日志");
}
}
7、如果希望获取相应的调用信息,可以通过JoinPoint这个参数进行配置
/**
* execution的写法
* 第一个‘*’表示任意返回值
* 第二个‘*’表示包中的所有类
* 第三个‘&’表示以Add开头的所有方法
* (..)表示任意参数
*/
@Before("execution("
+ "* " //返回值,为任何值
+ "spring.dao.*" //包名,包名下的所有类
+ ".add*" //方法名,以add开头的所有方法
+ "(..))" //方法的参数,两个句点表示任何参数
+ "||"
+ "execution(* spring.dao.*.delete(..))")
public void logStart(JoinPoint jPoint) {
//得到执行的对象
System.out.println(jPoint.getTarget());
//得到执行的方法
System.out.println(jPoint.getSignature().getName());
Logger.info("加入日志");
}
常用的注解整理
@Before
函数调用之前执行
/**
* execution的写法
* 第一个‘*’表示任意返回值
* 第二个‘*’表示包中的所有类
* 第三个‘&’表示以Add开头的所有方法
* (..)表示任意参数
*/
@Before("execution("
+ "* " //返回值,为任何值
+ "spring.dao.*" //包名,包名下的所有类
+ ".add*" //方法名,以add开头的所有方法
+ "(..))" //表示任意参数
+ "||"
+ "execution(* spring.dao.*.delete(..))")
public void logStart(JoinPoint jPoint) {
//得到执行的对象
System.out.println(jPoint.getTarget());
//得到执行的方法
System.out.println(jPoint.getSignature().getName());
Logger.info("加入日志");
}
@After
函数调用完成之后执行
@After("execution("
+ "* " //返回值,为任何值
+ "spring.dao.*" //包名,包名下的所有类
+ ".add*" //方法名,以add开头的所有方法
+ "(..))" //表示任意参数
+ "||"
+ "execution(* spring.dao.*.delete(..))")
public void logEnd(JoinPoint jPoint) {
Logger.info("方法调用结束");
}
@Around
函数调用的过程执行,开始到结束。
Around方法
@Around("execution("
+ "* " //返回值,为任何值
+ "spring.dao.*" //包名,包名下的所有类
+ ".add*" //方法名,以add开头的所有方法
+ "(..))" //表示任意参数
+ "||"
+ "execution(* spring.dao.*.delete(..))")
public void logAround(ProceedingJoinPoint jPoint) {
Logger.info("开始在Around加入日志");
try {
//执行方法
jPoint.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Logger.info("结束Around");
}
测试
spring.dao中的类
接口
public interface IUserDao {
public void add(User user);
public void delete(int id);
public User load(int id);
}
实现类
@Repository("userDao")
public class UserDao implements IUserDao {
@Override
public void add(User user) {
System.out.println("添加了 " + user.getName());
}
@Override
public void delete(int id) {
System.out.println("删除了" + id);
}
@Override
public User load(int id) {
System.out.println("加载了 " + id);
return null;
}
}
测试方法
@Test
public void testUser01() {
IUserDao dao=(IUserDao) factory.getBean("userDao");
User user = new User(1,"猴子");
dao.add(user);
}
执行结果
----开始在Around加入日志
spring.dao.UserDao@77659b30
add
----加入日志
添加了 猴子
----结束Around
----方法调用结束
由上可以看出,Around的触发是在Before之前,After之后的。(‘添加了 猴子’ 这句是测试方法的日志)
其中,我们需要调用ProceedingJoinPoint的proceed()方法,执行函数方法。如果我们将这个方法屏蔽掉,结果为:
----开始在Around加入日志
----结束Around
----方法调用结束
日志表明,我们实现@Around代理时,方法会在这里做通过管理,我们可以在这实现方法是否执行的逻辑判断,控制程序的运行。
因为方法未能执行,所以@Before的监听没有处罚,而截止方法后,@After触发了。## 标题 ##