背景:

写controller层时,不小心写了个private方法,恰巧项目中配了spring aop记录日志,抛出空指针异常

public方法可正常访问,private方法访问时,service为null

 

解决:

有两种解决思路:

1.修改private为public;

2.注释掉配置文件中的<aop:aspectj-autoproxy />,不过会导致@Aspect失效(不要使用此方法,老大会揍你的)。

 

原因:

从代理模式到spring aop

1、首先代理模式分为两大类:静态代理及动态代理

1)静态代理:jdk静态代理,更多的表示一种设计模式

主要包括三个要素:委托类、委托类具备的功能(接口)、代理类 

代理类实现接口,并持有委托类对象,代理委托类也可增强委托类功能

静态代理在编译期可确定,并生成字节码文件

2)动态代理:jdk代理、cglib代理

jdk代理:委托类与代理类实现相同接口

cglib代理:委托类继承代理类

为了减少代理类,jdk代理提供了InvocationHandler接口,cglib提供了MethodInterceptor接口

动态代理在运行时生成字节码文件

静态代理与动态代理有不能代理委托类的private方法及final方法:

    取个栗子:比如委托方是个传统手艺人,那么代理方无法代理

 

2、spring aop

spring aop通过代理实现,

如果目标没有实现任何接口,那么使用cglib代理

如果目标至少实现了一个接口,那么默认使用jdk代理,也可强制使用cglib代理

 

问:那么如果controller中存在private方法,并配置了aop,而且controller方法中的private方法匹配aop的aspect表达式,为什么会出现空指针的问题?

答:由于spring aop代理无法代理bean的private方法,那么会交给cglib代理,所以不包含spring容器中的bean,导致出现空指针异常

问:为什么spring aop代理失效时会交给cglib代理?

答:首先spring aop生成代理类中没有私有方法,而且被controller没有实现任何接口,那么只能通过cglib代理实现

问:spring什么时候使用代理,不使用代理?

答:spring在配置声明式事务@Transactional及@Aspect时使用代理,其他时候使用实例