spring mvc controller 私有方法处理

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 可以正常调用,作为代理对象时,会导致空指针异常,原因:注入调用链中的依赖对象为空。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值