Spring AOP的3种创建代理方式

前言

Spring AOP是大家都非常熟悉的一个概念,在Spring家族体系中扮演着举足轻重的作用。

然后Spring作为一个优秀的框架,提供了多种应用层面上代理的方式:ProxyFactoryBean、ProxyFactory、AspectJProxyFactory

而他们都继承于ProxyCreatorSupport。

注意:此处这里指的是Spring提供的应用层得方式,并不是指的底层实现方式。底层实现方式现在只有业界都熟悉的两种:JDK动态代理和CGLIB代理

ProxyCreatorSupport

在这里插入图片描述

public class ProxyCreatorSupport extends AdvisedSupport {

    //忽略代码....
    
    protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		//createAopProxy底层是DefaultAopProxyFactory的createAopProxy方法
		return getAopProxyFactory().createAopProxy(this);
	}

DefaultAopProxyFactorycreateAopProxy方法

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

     public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("...");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

ProxyFactoryBean

使用Spring提供的类org.springframework.aop.framework.ProxyFactoryBean是创建AOP的最基本的方式。
它是个工厂Bean,然后我们可以自定义我们的代理实现逻辑,最终交给Spring容器管理即可。

public class ProxyFactoryBean extends ProxyCreatorSupport
		implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {

	/**
	 * 拦截器列表中某个值的后缀表示要展开全局变量.
	 */
	public static final String GLOBAL_SUFFIX = "*";

	/**
	 * 需要植入进目标对象的bean列表 
	 * 此处需要注意:这些bean必须实现类 org.aopalliance.intercept.MethodInterceptor
	 * 或 org.springframework.aop.Advisor的bean ,配置中的顺序对应调用的顺序
	 */
	private String[] interceptorNames;

	@Nullable
	private String targetName;

	private boolean autodetectInterfaces = true;

	private boolean singleton = true;

	private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

	private boolean freezeProxy = false;

	@Nullable
	private transient ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();

	private transient boolean classLoaderConfigured = false;

	@Nullable
	private transient BeanFactory beanFactory;

	/** advisor链是否已初始化 */
	private boolean advisorChainInitialized = false;

	/** 如果这是singleton,则缓存的singleton代理实例。 */
	@Nullable
	private Object singletonInstance;


    //返回对象的实例(可能是共享的或独立的)
	public Object getObject() throws BeansException {
	    //就是根据我们配置的interceptorNames来获取对应的bean,并却转化成Advisor。
		//this.advisorChainInitialized:标示是否已进行过初始化,若以初始化则不再进行初始化。
		initializeAdvisorChain();
		if (isSingleton()) {
			return getSingletonInstance();
		}
		else {
			if (this.targetName == null) {logger.info(".....");}
			return newPrototypeInstance();
		}
	}


   private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
       //是否已进行过初始化,若以初始化则不再进行初始化
		if (this.advisorChainInitialized) {
			return;
		}
         //如果我们配置的interceptorNames不为空
		if (!ObjectUtils.isEmpty(this.interceptorNames)) {
			if (this.beanFactory == null) {throw new IllegalStateException("....."));}
			//除非我们使用属性指定了targetSource,否则全局变量不能是最后一个。。。
			if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
					this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
				throw new AopConfigException(".....");
			}

			// 从bean名称具体化拦截器链
			for (String name : this.interceptorNames) {
				if (logger.isTraceEnabled()) {logger.trace("");}
                 // 如国拦截器的名称是以*结尾的,说明它要去全局里面都搜索出来
				if (name.endsWith(GLOBAL_SUFFIX)) {
					if (!(this.beanFactory instanceof ListableBeanFactory)) {
						throw new AopConfigException(".....");
					}
					addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
							name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
				}
              // 如国拦截器的名称是不以*结尾的
				else {
					//如果我们到了这里,我们需要添加一个命名的拦截器。
                    //我们必须检查它是单例还是原型。
					Object advice;
		            //单例
					if (this.singleton || this.beanFactory.isSingleton(name)) {
						//创建,并把这个Bean把从容器里拿出来
						advice = this.beanFactory.getBean(name);
					}
					//原型
					else {
						//这是一个原型建议或顾问:用原型替换。
                        //避免仅仅为了advisor链初始化而不必要地创建原型bean。
						advice = new PrototypePlaceholderAdvisor(name);
					}
					//把bean转换成Advisor,并放在其Advisor链中
					addAdvisorOnChainCreation(advice, name);
				}
			}
		}
		this.advisorChainInitialized = true;
	}

   private void addAdvisorOnChainCreation(Object next, String name) {
		//把bean转换成Advisor
		Advisor advisor = namedBeanToAdvisor(next);
		if (logger.isTraceEnabled()) {logger.trace("Adding advisor with name '" + name + "'");}
		//将其放在Advisor链中
		addAdvisor(advisor);
	}

  //底层使用DefaultAdvisorAdapterRegistry的wrap方法
   private Advisor namedBeanToAdvisor(Object next) {
		try {
			return this.advisorAdapterRegistry.wrap(next);
		}
		catch (UnknownAdviceTypeException ex) {
			....
		}
	}
  • 使用DefaultAdvisorAdapterRegistry把bean包装成Advisor对象
@Override
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		//如果对象是Advisor类型,直接转换
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		//对象必须是Advice类型
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		//把对象转换成Advice类型
		Advice advice = (Advice) adviceObject;
		//如果是MethodInterceptor类型
		if (advice instanceof MethodInterceptor) {
			//众所周知,它甚至不需要适配器。
			return new DefaultPointcutAdvisor(advice);
		}
		//如果是Advice类型但不是如果是MethodInterceptor类型类型,需要检查是否支持
		for (AdvisorAdapter adapter : this.adapters) {
			//检查它是否受支持。
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

案例

@Component("logMethodBeforeAdvice")
public class LogMethodBeforeAdvice implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("this is LogMethodBeforeAdvice");
    }
}

// 注册一个代理Bean
@Bean
public ProxyFactoryBean proxyFactoryBean(HelloService helloService) {
        ProxyFactoryBean factoryBean = new ProxyFactoryBean();

        //代理的目标对象  效果同setTargetSource(@Nullable TargetSource targetSource)
        // 此处需要注意的是,这里如果直接new,那么该类就不能使用@Autowired之类的注入  因此建议此处还是从容器中去拿
        // 因此可以写在入参上(这也是标准的写法~~)
        //factoryBean.setTarget(new HelloServiceImpl());
        factoryBean.setTarget(helloService);

        // setInterfaces和setProxyInterfaces的效果是相同的。设置需要被代理的接口,
        // 若没有实现接口,那就会采用cglib去代理
        // 需要说明的一点是:这里不设置也能正常被代理(若你没指定,Spring内部会去帮你找到所有的接口,然后全部代理上~~~~~~~~~~~~)  
        //设置的好处是只代理指定的接口
        factoryBean.setInterfaces(HelloService.class);
        //factoryBean.setProxyInterfaces(new Class[]{HelloService.class});

        // 需要植入进目标对象的bean列表 此处需要注意:
        //这些bean必须实现类 org.aopalliance.intercept.MethodInterceptor或 
        //org.springframework.aop.Advisor的bean ,配置中的顺序对应调用的顺序
        factoryBean.setInterceptorNames("logMethodBeforeAdvice");

        // 若设置为true,强制使用cglib,默认是false的
        //factoryBean.setProxyTargetClass(true);

        return factoryBean;
    }

// main方法测试:
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class);

        //expected single matching bean but found 2: helloServiceImpl,proxyFactoryBean
        // 如果通过类型获取,会找到两个Bean:一个我们自己的实现类、一个ProxyFactoryBean所生产的代理类 而此处我们显然是希望要生成的代理类的  因此我们只能通过名称来(或者加上@Primary)
        //HelloService bean = applicationContext.getBean(HelloService.class);
        HelloService bean = (HelloService) applicationContext.getBean("proxyFactoryBean");
        bean.hello();
        
        System.out.println(bean); //com.fsx.service.HelloServiceImpl@4e50c791
        System.out.println(bean.getClass()); //class com.sun.proxy.$Proxy22 用得JDK的动态代理
        // 顺便说一句:这样也是没错得。因为Spring AOP代理出来的每个代理对象,都默认实现了这个接口(它是个标记接口)
        // 它这个也就类似于所有的JDK代理出来的,都是Proxy的子类是一样的思想~
        SpringProxy springProxy = (SpringProxy) bean;
    }

ProxyFactory

public class ProxyFactory extends ProxyCreatorSupport {

	//无自己的属性
	public ProxyFactory() {
	}

	
	public ProxyFactory(Object target) {
		setTarget(target);
		setInterfaces(ClassUtils.getAllInterfaces(target));
	}

	public ProxyFactory(Class<?>... proxyInterfaces) {
		setInterfaces(proxyInterfaces);
	}

	public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
		addInterface(proxyInterface);
		addAdvice(interceptor);
	}

	public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {
		addInterface(proxyInterface);
		setTargetSource(targetSource);
	}

   //获取代理对象
	public Object getProxy() {
		return createAopProxy().getProxy();
	}

案例

ProxyFactory proxyFactory = new ProxyFactory(new HelloServiceImpl());

// 添加两个Advise,一个匿名内部类表示
proxyFactory.addAdvice((AfterReturningAdvice)(returnValue, method, args1, target) ->
System.out.println("AfterReturningAdvice method=" + method.getName()));

HelloService proxy = (HelloService) proxyFactory.getProxy();
proxy.hello();

AspectJProxyFactory

在Spring2.0以前定义一个切面是比较麻烦的,需要实现特定的接口,并进行一些较为复杂的配置。在Spring2.0后,Spring AOP已经焕然一新,你可以使用@AspectJ注解非常容易的定义一个切面,不需要实现任何的接口,这都是AspectJProxyFactory的功劳

AspectJ是目前大家最常用的 起到集成AspectJ和Spring,也就是我们平时长谈的:自动代理模式。它整个代理的过程全部交给Spring内部去完成,无侵入。

我们只需要配置切面、通知、切点表达式就能自动的实现切入的效果,使用起来极其方便,对调用者可以说是非常透明化的。相信这也是为何当下最流行这种方式的原因~

public class AspectJProxyFactory extends ProxyCreatorSupport {
	/** Cache for singleton aspect instances */
	private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<>();
	//基于AspectJ时,创建Spring AOP的Advice  下面详说
	private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();

	public AspectJProxyFactory() {
	}
	public AspectJProxyFactory(Object target) {
		Assert.notNull(target, "Target object must not be null");
		setInterfaces(ClassUtils.getAllInterfaces(target));
		setTarget(target);
	}
	public AspectJProxyFactory(Class<?>... interfaces) {
		setInterfaces(interfaces);
	}

	// 这两个addAspect方法是最重要的:我们可以把一个现有的aspectInstance传进去,当然也可以是一个Class(下面)======
	public void addAspect(Object aspectInstance) {
		Class<?> aspectClass = aspectInstance.getClass();
		String aspectName = aspectClass.getName();
		
		AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
		// 显然这种直接传实例进来的,默认就是单例的。不是单例我们就报错了~~~~
		if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) {
			throw new IllegalArgumentException(
					"Aspect class [" + aspectClass.getName() + "] does not define a singleton aspect");
		}
		
		// 这个方法就非常的关键了~~~ Singleton...是它MetadataAwareAspectInstanceFactory的子类
		addAdvisorsFromAspectInstanceFactory(
				new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, aspectName));
	}
	public void addAspect(Class<?> aspectClass) {
		String aspectName = aspectClass.getName();
		AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
		MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName);
		addAdvisorsFromAspectInstanceFactory(instanceFactory);
	}

	// 从切面工厂里,把对应切面实例里面的增强器(通知)都获取到~~~
	private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
		// 从切面工厂里,先拿到所有的增强器们~~~
		List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
		Class<?> targetClass = getTargetClass();
		Assert.state(targetClass != null, "Unresolvable target class");
		advisors = AopUtils.findAdvisorsThatCanApply(advisors, targetClass);
		AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
		AnnotationAwareOrderComparator.sort(advisors);
		addAdvisors(advisors);
	}
}

案例

@Aspect
public class MyAspect {

	@Pointcut("execution(* hello(..))")
	private void beforeAdd() {
	}

	@Before("beforeAdd()")
	public void before1() {
		System.out.println("-----------before-----------");
	}

}
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new HelloServiceImpl());
		// 注意:此处得MyAspect类上面的@Aspect注解必不可少
proxyFactory.addAspect(MyAspect.class);
		//proxyFactory.setProxyTargetClass(true);//是否需要使用CGLIB代理
		HelloService proxy = proxyFactory.getProxy();
		proxy.hello();

		System.out.println(proxy.getClass()); //

注意:
需要注意的是在使用AspectjProxyFactory基于切面类创建代理对象时,我们指定的切面类上必须包含@Aspect注解。
虽然我们自己通过编程的方式可以通过AspectjProxyFactory创建基于@Aspect标注的切面类的代理,但是通过配置aop:aspectj-autoproxy/(@EnableAspectJAutoProxy)使用基于注解的Aspectj风格的Aop时,Spring内部不是通过AspectjProxyFactory创建的代理对象,而是通过ProxyFactory(这个在分析自动代理源码的时候有说到过~~~~)

总结

这三个类本身没有什么关系,但都继承自:ProxyCreatorSupport,创建代理对象的核心逻辑都是在ProxyCreatorSupport的createAopProxy方法中实现的。

AspectJProxyFactory,ProxyFactoryBean,ProxyFactory 大体逻辑如下:

1、填充AdvisedSupportProxyCreatorSupport是其子类)

2、交给父类ProxyCreatorSupport处理调用createAopProxy方法得到JDK或者CGLIB的AopProxy代理对象。

3、调用这个代理对象时,会被invoke或者intercept方法拦截 (在JdkDynamicAopProxyCglibAopProxy中), 并且在这两个方法中调用ProxyCreatorSupportgetInterceptorsAndDynamicInterceptionAdvice方法去初始化advice和各个方法直接映射关系并缓存

发布了34 篇原创文章 · 获赞 0 · 访问量 1366

猜你喜欢

转载自blog.csdn.net/qq_41071876/article/details/104613895