背景:
写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时使用代理,其他时候使用实例