spring aop 日志
之前开发项目,一直都是在service 的方法里面增加日志,每次都要写,感觉繁琐,自己研究了spring aop来进行日志管理.
在这里就不扯理论知识了,这里讲四中aop的实现来进行日志管理.
四种方式,首先考虑的为第一种基于@Aspect方式
如果使用的为低版本的JDK,可以考虑
如果升级一个低版本的spring aop 那么可以使用<aop:advisor>
复用已经存在的advice类
如果使用低版本的spring那么可以使用Advisor
1:基于@Aspect注解形式
注意,jdk要支持这个注解
@Aspect//切面
public class MyLog {
protected Logger logger = Logger.getLogger(this.getClass());
@Before("execution(* wsylp.service.UserService.*(..))")//定义切面
public void logBegin(JoinPoint point) {
logger.info("@Before:前置增强:" + point.getSignature().getDeclaringTypeName() + "." + point
.getSignature().getName());
}
@AfterReturning("execution(* wsylp.service.UserService.*(..))")//定义切面
public void logAfter(JoinPoint point) {
logger.info(
"@AfterReturning:后置增强:" + point.getSignature().getDeclaringTypeName() + "." + point
.getSignature().getName());
}
@Around("execution(* wsylp.service.UserService.*(..))")//定义切面
public void logAround(ProceedingJoinPoint point) throws Throwable {
logger.info("环绕增强开始...........");
logger.info(point.getTarget().getClass());
point.proceed();
logger.info("@Around:环绕增强方法:" + point.getSignature().getDeclaringTypeName() + "." + point
.getSignature().getName());
logger.info("环绕增强结束...........");
}
}
配置文件
<!-- 注解aspect-->
<aop:aspectj-autoproxy/>
<bean class="wsylp.log.MyLog"></bean>
测试以及结果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:spring-*.xml")
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void getUser() {
userService.getList();
}
}
结果
[wsylp.log.MyLog] - @Around:环绕增强方法开始:wsylp.service.UserService.getList
[wsylp.log.MyLog] - @Before:前置增强:wsylp.service.UserService.getList
[wsylp.service.impl.UserServiceImpl] - getList方法开始
[wsylp.service.impl.UserServiceImpl] - getList方法结束
[wsylp.log.MyLog] - @Around:环绕增强方法结束:wsylp.service.UserService.getList
[wsylp.log.MyLog] - @AfterReturning:后置增强:wsylp.service.UserService.getList
2:基于aop:aspect方式
public class LogSchema {
protected Logger logger = Logger.getLogger(this.getClass());
public void logBefore(JoinPoint point) {
logger.info(
"前置增强:" + point.getSignature().getDeclaringTypeName() + "." + point.getSignature()
.getName());
}
public void logAfter(JoinPoint point) {
logger.info(
"后置增强:" + point.getSignature().getDeclaringTypeName() + "." + point.getSignature()
.getName());
}
//环绕增强对应方法
public void logAround(ProceedingJoinPoint pjp) throws Throwable {
logger.info("环绕增强开始:"+pjp.getSignature().getDeclaringTypeName()+"."+pjp.getSignature().getName());
pjp.proceed();
logger.info("环绕增强结束:"+pjp.getSignature().getDeclaringTypeName()+"."+pjp.getSignature().getName());
}
//抛出异常增强
public void afterThrowingMethod(IllegalArgumentException iae) {
System.out.println("----afterThrowingMethod()----");
System.out.println("exception msg:" + iae.getMessage());
System.out.println("----afterThrowingMethod()----");
}
//final增强
public void afterMethod() {
System.out.println("----afterMethod()----");
}
}
配置文件
<aop:config proxy-target-class="true">
<aop:aspect ref="logSchema" >
<aop:pointcut id="logPoint" expression="target(wsylp.service.impl.UserServiceImpl)"/>
<aop:before method="logBefore" pointcut-ref="logPoint"></aop:before>
<aop:after-returning method="logAfter" pointcut-ref="logPoint"></aop:after-returning>
<aop:around method="logAround" pointcut-ref="logPoint"></aop:around>
</aop:aspect>
</aop:config>
<bean id="logSchema" class="wsylp.log.schema.LogSchema"></bean>
测试以及结果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:spring-*.xml")
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void getUser() {
userService.getList();
}
}
结果:
[wsylp.log.schema.LogSchema] - 前置增强:wsylp.service.impl.UserServiceImpl.getList
[wsylp.log.schema.LogSchema] - 环绕增强开始:wsylp.service.impl.UserServiceImpl.getList
[wsylp.service.impl.UserServiceImpl] - getList方法开始
[wsylp.service.impl.UserServiceImpl] - getList方法结束
[wsylp.log.schema.LogSchema] - 环绕增强结束:wsylp.service.impl.UserServiceImpl.getList
[wsylp.log.schema.LogSchema] - 后置增强:wsylp.service.impl.UserServiceImpl.getList
3:基于aop:advisor方式
前置增强
public class LogAdvisorBefore implements MethodBeforeAdvice {
protected Logger logger = Logger.getLogger(this.getClass());
public void before(Method method, Object[] args, Object target) throws Throwable {
logger.info("前置增强:"+method.getDeclaringClass()+"."+method.getName());
}
}
后置增强
public class LogAdvisorAfter implements AfterReturningAdvice {
protected Logger logger = Logger.getLogger(this.getClass());
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1)
throws Throwable {
logger.info("后置增强:"+method.getDeclaringClass()+"."+method.getName());
}
}
环绕增强
public class LogAdvisorAround implements MethodInterceptor {
protected Logger logger = Logger.getLogger(this.getClass());
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
logger.info(
"环绕增强开始=>" + methodInvocation.getMethod().getDeclaringClass() + "." + methodInvocation
.getMethod().getName());
Object obj = methodInvocation.proceed();
//在目标执行后调用
logger.info(
"环绕增强结束=>" + methodInvocation.getMethod().getDeclaringClass() + "." + methodInvocation
.getMethod().getName());
return obj;
}
}
配置文件
<aop:config proxy-target-class="true">
<aop:advisor advice-ref="logBefore" pointcut="execution(* wsylp..*.UserService.*(..))" />
<aop:advisor advice-ref="logAfter" pointcut="execution(* wsylp..*.UserService.*(..))" />
<aop:advisor advice-ref="logAround" pointcut="execution(* wsylp..*.UserService.*(..))" />
</aop:config>
<bean id="logBefore" class="wsylp.log.advisor.LogAdvisorBefore"></bean>
<bean id="logAfter" class="wsylp.log.advisor.LogAdvisorAfter"></bean>
<bean id="logAround" class="wsylp.log.advisor.LogAdvisorAround"></bean>
测试以及结果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:spring-*.xml")
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void getUser() {
userService.getList();
}
}
结果
[wsylp.log.advisor.LogAdvisorBefore] - 前置增强:class wsylp.service.impl.UserServiceImpl.getList
[wsylp.log.advisor.LogAdvisorAround] - 环绕增强开始=>class wsylp.service.impl.UserServiceImpl.getList
[wsylp.service.impl.UserServiceImpl] - getList方法开始
[wsylp.service.impl.UserServiceImpl] - getList方法结束
[wsylp.log.advisor.LogAdvisorAround] - 环绕增强结束=>class wsylp.service.impl.UserServiceImpl.getList
[wsylp.log.advisor.LogAdvisorAfter] - 后置增强:class wsylp.service.impl.UserServiceImpl.getList
4:基于advisor类
静态方法代理
public class LogAdvisor extends StaticMethodMatcherPointcutAdvisor{
@Override
public boolean matches(Method method, Class<?> aClass) {
return true;
}
public ClassFilter getClassFilter(){
return new ClassFilter() {
@Override
public boolean matches(Class<?> aClass) {
return UserServiceImpl.class.isAssignableFrom(aClass);
}
};
}
}
前置增强
public class LogBeforeAdvice implements MethodBeforeAdvice {
protected Logger logger = Logger.getLogger(this.getClass());
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
logger.info("基于advisor->前置增强"+"方法名:" + o.getClass().getName() + "." + method.getName() + "()");
}
}
后置增强
public class LogBeforeAdvice implements MethodBeforeAdvice {
protected Logger logger = Logger.getLogger(this.getClass());
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
logger.info("基于advisor->前置增强"+"方法名:" + o.getClass().getName() + "." + method.getName() + "()");
}
}
配置文件
我采用的是ssm框架,大家把配置文件配好,日志写好,就可以直接使用
<!--低版本spring 基于advisor类-->
<bean id="logBeforeAdvice" class="wsylp.log.advisorC.LogBeforeAdvice"></bean>
<bean id="logAfterAdvice" class="wsylp.log.advisorC.LogAfterAdvice"></bean>
<bean id="logAdvisorB" class="wsylp.log.advisorC.LogAdvisor"
p:advice-ref="logBeforeAdvice" />
<bean id="logAdvisorA" class="wsylp.log.advisorC.LogAdvisor"
p:advice-ref="logAfterAdvice" />
<bean id="parent" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="logAdvisorB,logAdvisorA"
p:proxyTargetClass="true"
></bean>
<bean id="userService1" parent="parent" p:target-ref="userService"></bean>
注意由于采用的是代理,bean的名字用userService1,而target-ref引用的为userService配置的bean,大家可以自己修改
测试代码以及结果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:spring-*.xml")
public class UserServiceTest {
@Autowired
private UserService userService1;
@Test
public void getUser() {
userService1.getList();
}
}
结果
[wsylp.log.advisorC.LogBeforeAdvice] - 基于advisor->前置增强方法名:wsylp.service.impl.UserServiceImpl.getList()
[wsylp.service.impl.UserServiceImpl] - getList方法开始
[wsylp.service.impl.UserServiceImpl] - getList方法结束
[wsylp.log.advisorC.LogAfterAdvice] - 基于advisor->后置增强方法名:wsylp.service.impl.UserServiceImpl.getList()