Spring MVC Controller 私有方法处理
- 1.Controller 作为普通bean 调用
- 2.Controller 作为代理对象调用
请看以下代码来自于Spring 官方文档:
public class SpringProxy {
interface Pojo {
void foo();
}
public static class SimplePojo implements Pojo {
@Override
public void foo() {
System.out.println("foo...");
}
}
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice((MethodInterceptor) invocation -> {
try {
System.out.println("before...");
return invocation.proceed();
} finally {
System.out.println("after...");
}
});
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
提示: 此篇文章不是专门讲Spring Aop代理模式的实现逻辑的,所以只是略过一下;有兴趣的可以查看Spring AOP 代理设计思想理念及源代码实现
关于 DI 依赖注入逻辑请看:依赖注入
简单看一下ProxyFactory 这个类的结构及factory.getProxy()调用
public ProxyFactory(Object target) {
//设置目标对象--> SingletonTargetSource(target)
setTarget(target);
setInterfaces(ClassUtils.getAllInterfaces(target));
}
//创建代理对象
public Object getProxy() {
return createAopProxy().getProxy();
}
//--此方法来自于parent类AdvisedSupport
public void setTarget(Object target) {
setTargetSource(new SingletonTargetSource(target));
}
//配置需要代理的接口。--此方法来自于parent类AdvisedSupport
public void setInterfaces(Class<?>... interfaces) {
Assert.notNull(interfaces, "Interfaces must not be null");
this.interfaces.clear();
for (Class<?> ifc : interfaces) {
addInterface(ifc);
}
}
//添加一个新的代理接口。--此方法来自于parent类AdvisedSupport
public void addInterface(Class<?> intf) {
Assert.notNull(intf, "Interface must not be null");
if (!intf.isInterface()) {
throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
}
if (!this.interfaces.contains(intf)) {
this.interfaces.add(intf);
adviceChanged();
}
}
//添加通知Advice---此方法来自于parent类AdvisedSupport
@Override
public void addAdvice(Advice advice) throws AopConfigException {
int pos = this.advisors.size();
addAdvice(pos, advice);
}
factory.getProxy()
//创建代理
public Object getProxy() {
return createAopProxy().getProxy();
}
//来获得一个新的AOP代理;默认为 DefaultAopProxyFactory ---此方法来自于parent类ProxyCreatorSupport;
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
///....AdvisedSupport 的一些其他项配置请参阅Spring framework 官网这里不做过多解释。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//1.Optimize:控制是否将主动优化应用于通过CGLIB创建的代理。。。目前仅用于CGLIB代理。它对JDK动态代理没有影响
//2.ProxyTargetClass: 要代理目标类,而不是目标类的接口。此属性值设置为true,则创建CGLIB代理(但也要参阅基于JDK和基于CGLIB的代理)。
//3.hasNoUserSuppliedProxyInterfaces:没有用户提供的代理接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
//确定所提供的AdvisedSupport是否只有指定SpringProxy接口或者根本没有指定代理接口。
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
private私有方法调用:
![在这里插入图片描述](https://img-blog.csdnimg.cn/44a93aa5f81047dbb9594d7f3849aea5.png#pic_center
public公有修饰符调用:
来看一下Cglib代理类生成的逻辑:
让我们来看一下生成的字节码文件:
图中可以看出queryPublic方法被重写了。
结论:方法修饰符为私有(private)时,Spring MVC 中 Controller 作为普通bean 可以正常调用,作为代理对象时,会导致空指针异常,原因:注入调用链中的依赖对象为空。