spring AOP可以对方法进行加强,就是在方法前执行一些想要的事情,执行方法后想执行一些信息,原理就是利用动态代理,具体不在阐述
今天要讨论的是一个springBean继承了父类,在父类里进行了方法加强,子类调用父类的方法,父类方法会加强吗?
注解@CommonLogger是我利用AOP Aspect写的一个打印方法参数的注解,就是在方法上加了这个注解,这个方法的参数就会打印出来,并且对日志进行了脱敏处理
现在有以下父类
public class LogFilterServiceParent {
private Logger logger = LoggerFactory.getLogger(getClass());
@CommonLogger(positions={Position.PARAMTER})
public void log2(OrderDetailDTO dto,String str) {
logger.info("--------------------------------LogFilterServiceParent---------------------------");
}
}
子类
@Service
public class LogFilterServiceImpl extends LogFilterServiceParent implements LogFilterService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void log(OrderDetailDTO dto,String str) {
this.log2(dto, str);
logger.info("--------------------------------LogFilterServiceImpl---------------------------");
}
}
public interface LogFilterService {
void log(OrderDetailDTO dto,String str);
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)//其他相关配置省去
public class LogFilterServiceTest extends BaseSARTest {
@Autowired
private LogFilterService logFilterService;
private Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void testLogFilter() {
OrderDetailDTO dto = new OrderDetailDTO();
NbiCustomerInfoDTO custom = new NbiCustomerInfoDTO();
custom.setBirthday("2016-02-25");
custom.setDetailAddress("广东生深圳市罗湖区大剧院京基100大厦");
custom.setEmail("[email protected]");
custom.setCardId("440515199212237208");
custom.setMobileNo("13698545691");
custom.setName("张山疯");
dto.setApplyPolicyNo("12365998");
dto.setCurrentSysDate(new Date());
dto.setOrderNo("AA201807130849120300010000001");
dto.setPolicyHolder(custom);
List list = new ArrayList();
list.add(custom);
list.add(custom1);
dto.setCustomerInfoList(list);
dto.setOrderStatus(2);
logFilterService.log(dto,"440515199212237208");
}
}
我想达到的效果是,LogFilterServiceImpl调用父类的log2方法,log2方法能够打印入参,但实际上没有打印,并且报了以下错误
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
[14:30:23.235] [DEBUG] [
没懂这个报错的意思
按照继承的规则,子类自动拥有父类的方法,按理应该spring会给加了注解的方法加强,但实际上没有
查阅spring aop相关的内容,发现spring AOP不支持同类方法调用,意思就是同一个spring Bean中,如果多个方法中都用了方法加强,一个方法调用了另外一个方法,另外一个方法(被调用方法)是无法加强的,于是我改了一下
在子类的接口中增加父类的方法
public interface LogFilterService {
void log(OrderDetailDTO dto,String str);
void log2(OrderDetailDTO dto,String str);
}
测试类直接调用父类的这个方法log2,测试方法改成如下
@Test
public void testLogFilter() {
OrderDetailDTO dto = new OrderDetailDTO();
NbiCustomerInfoDTO custom = new NbiCustomerInfoDTO();
custom.setBirthday("2016-02-25");
custom.setDetailAddress("广东生深圳市罗湖区大剧院京基100大厦");
custom.setEmail("[email protected]");
custom.setCardId("440515199212237208");
custom.setMobileNo("13698545691");
custom.setName("张山疯");
dto.setApplyPolicyNo("12365998");
dto.setCurrentSysDate(new Date());
dto.setOrderNo("AA201807130849120300010000001");
dto.setPolicyHolder(custom);
List list = new ArrayList();
list.add(custom);
list.add(custom1);
dto.setCustomerInfoList(list);
dto.setOrderStatus(2);
logFilterService.log2(dto,"440515199212237208");//这里有变化
}
发现日志打印出来了,意思就是父类的方法加强起效了,然我又把带接口的方式放到方法log中,如下
@Service
public class LogFilterServiceImpl extends LogFilterServiceParent implements LogFilterService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void log(OrderDetailDTO dto,String str) {
this.log2(dto, str);
logger.info("--------------------------------LogFilterServiceImpl---------------------------");
}
}
测试类
@Test
public void testLogFilter() {
OrderDetailDTO dto = new OrderDetailDTO();
NbiCustomerInfoDTO custom = new NbiCustomerInfoDTO();
custom.setBirthday("2016-02-25");
custom.setDetailAddress("广东生深圳市罗湖区大剧院京基100大厦");
custom.setEmail("[email protected]");
custom.setCardId("440515199212237208");
custom.setMobileNo("13698545691");
custom.setName("张山疯");
dto.setApplyPolicyNo("12365998");
dto.setCurrentSysDate(new Date());
dto.setOrderNo("AA201807130849120300010000001");
dto.setPolicyHolder(custom);
List list = new ArrayList();
list.add(custom);
list.add(custom1);
dto.setCustomerInfoList(list);
dto.setOrderStatus(2);
logFilterService.log(dto,"440515199212237208");//这里有变化
}
发现还是不能打印日志,正对这种情况我又百度了一下,要使调用本类的方法并且是方法加强有效,则必须使用以下方式
在spring配置文件中,aop:aspectj-autoproxy 标签增加expose-proxy="true"属性,如下配置
public class LogFilterServiceParent {
private Logger logger = LoggerFactory.getLogger(getClass());
@CommonLogger(positions={Position.PARAMTER})
public void log2(OrderDetailDTO dto,String str) {
//logger.debug(sensitivityMessageFilter.doSensitivityFilter(dto));
logger.info("--------------------------------LogFilterServiceParent---------------------------");
}
}
然后子类调用父类的log2方法用以下方式调用
public void log(OrderDetailDTO dto,String str) {
((LogFilterServiceImpl)AopContext.currentProxy()).log2(dto, str);
logger.info("--------------------------------LogFilterServiceImpl---------------------------");
}
然后在调用测试类
@Test
public void testLogFilter() {
OrderDetailDTO dto = new OrderDetailDTO();
NbiCustomerInfoDTO custom = new NbiCustomerInfoDTO();
custom.setBirthday("2016-02-25");
custom.setDetailAddress("广东生深圳市罗湖区大剧院京基100大厦");
custom.setEmail("[email protected]");
custom.setCardId("440515199212237208");
custom.setMobileNo("13698545691");
custom.setName("张山疯");
dto.setApplyPolicyNo("12365998");
dto.setCurrentSysDate(new Date());
dto.setOrderNo("AA201807130849120300010000001");
dto.setPolicyHolder(custom);
List list = new ArrayList();
list.add(custom);
list.add(custom1);
dto.setCustomerInfoList(list);
dto.setOrderStatus(2);
logFilterService.log(dto,"440515199212237208");//这里有变化
}
发现可以打印日志了
the params of com.shux.trade.online.service.LogFilterServiceParent.log2 is :dto:{"orderNo":"IC201807130849120300010000001","currentSysDate":1547541805585,"policyHolder":{"cardId":"4****************8","birthday":"******","email":"******@qq.com","name":"*山疯","mobileNo":"1369****691","sortNumber":0,"detailAddress":"广东生深圳市罗湖区******"},"orderStatus":2,"customerInfoList":[{"cardId":"4****************8","birthday":"******","email":"******@qq.com","name":"*山疯","sortNumber":0,"mobileNo":"1369****691","detailAddress":"广东生深圳市罗湖区******"},{"cardId":"4****************8","birthday":"******","email":"******@qq.com","name":"*山疯","sortNumber":0,"mobileNo":"1332****424","detailAddress":"广东生深圳市罗湖区******"}],"applyPolicyNo":"12365998"},str:"4****************8"
为什么会这样?为什么直接掉没有用
其实这个也很简单,大家都知道spring的AOP其实是动态代理,没有走AOP加强说明了没有走代理,根据spring的springBean自动注入和动态代理
自动注入的都是其他类,自己是不会注入到自己本类的,自然就没有自动注入代理类了,自己掉自己没有走代理,自然就不会有加强了
为了解决这种问题,spring提供了AopContext类。
到时这样做会比较麻烦,大师们有更好的办法吗?