龙空技术网

搜狗3面:说说你对Spring AOP创建代理对象的源码理解

麒麟Java工程师 178

前言:

现在朋友们对“aop代理对象在什么时候创建”都比较关怀,小伙伴们都需要剖析一些“aop代理对象在什么时候创建”的相关资讯。那么小编也在网摘上汇集了一些关于“aop代理对象在什么时候创建””的相关知识,希望看官们能喜欢,你们一起来了解一下吧!

前言

Spring AOP 是 Spring 核心功能之一,日常的工作少不了和 AOP 打交道;是时候有必要去了解 Spring 对 AOP 创建代理其背后的原理,这样子我们才能写出更加高质量的代码及产生 BUG 的原因。

小编今天主要带大家了解 AOP 的一些概念,AOP 的实现方式有哪些,最主要还是介绍 Spring AOP 的创建代理和对象源码。

读者福利:转发+关注 私信【学习笔记】获取小编整理好的Java知识点学习笔记一份。

1、 工程简介1.1 pom

  <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <maven.compiler.source>1.8</maven.compiler.source>        <maven.compiler.target>1.8</maven.compiler.target>        <spring.version>5.2.8.RELEASE</spring.version>    </properties>    <dependencies>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.13</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>${spring.version}</version>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.16.20</version>        </dependency>        <!-- 日志相关依赖 -->        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-api</artifactId>            <version>1.7.10</version>        </dependency>        <dependency>            <groupId>ch.qos.logback</groupId>            <artifactId>logback-classic</artifactId>            <version>1.1.2</version>        </dependency>        <dependency>            <groupId>ch.qos.logback</groupId>            <artifactId>logback-core</artifactId>            <version>1.1.2</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-aspects</artifactId>            <version>${spring.version}</version>        </dependency>    </dependencies>
1.2 AOP配置文件
@Configuration@EnableAspectJAutoProxy@Import({ServiceAopConfig.class, DaoAopConfig.class})public class AopConfig {}@Configuration@Aspectpublic class DaoAopConfig {    /**     * 声明切点     */    @Pointcut("execution(* com.rosh.dao.*.*(..))")    public void pointCut() {    }    @Around("pointCut()")    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {        System.out.println("DaoAopConfig invoke around start");        Object proceed = proceedingJoinPoint.proceed();        System.out.println("DaoAopConfig invoke around end");        return proceed;    }}@Configuration@Aspectpublic class ServiceAopConfig {    /**     * 声明切点     */    @Pointcut("execution(* com.rosh.service.*.*(..))")    public void pointCut() {    }    @Around("pointCut()")    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {        System.out.println("ServiceAopConfig invoke around start");        Object proceed = proceedingJoinPoint.proceed();        System.out.println("ServiceAopConfig invoke around end");        return proceed;    }    @Before("pointCut()")    public void before(){        System.out.println("ServiceAopConfig invoke before");    }    @After("pointCut()")    public void after() {        System.out.println("ServiceAopConfig invoke after");    }}
1.3 StudentDao
@Repositorypublic class StudentDao {    public void addStudent() {        System.out.println("StudentDao invoke addStudent");    }}
1.4 Service
public interface StudentService {     void addStudent();}@Servicepublic class StudentServiceImpl implements StudentService {    @Override    public void addStudent() {        System.out.println("StudentServiceImpl invoke addStudent()");    }}
1.5 RoshTest
public class RoshTest {    @Test    public void mainTest(){        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.rosh");        StudentService studentService = (StudentService) applicationContext.getBean("studentServiceImpl");        studentService.addStudent();        System.out.println("===============分割线================");        StudentDao studentDao=(StudentDao) applicationContext.getBean("studentDao");        studentDao.addStudent();    }}
2、AbstractAutoProxyCreator概述

描述: 该类作用在,Spring Aop初始化源码分析中具体分析过,核心作用是,在bean初始化时,后置加强。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {			return bean;		}		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {			return bean;		}		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {			this.advisedBeans.put(cacheKey, Boolean.FALSE);			return bean;		}		// Create proxy if we have advice.		/**		 * 【1】获取当前bean有效的Advisor,Advisor = advice + pointCut		 */		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);		if (specificInterceptors != DO_NOT_PROXY) {			this.advisedBeans.put(cacheKey, Boolean.TRUE);			/**			 * 【2】创建代理对象			 */			Object proxy = createProxy(					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));			this.proxyTypes.put(cacheKey, proxy.getClass());			return proxy;		}		this.advisedBeans.put(cacheKey, Boolean.FALSE);		return bean;	}
3 创建代理对象源码解析3.1 createProxy

描述: 主流程调用方法AbstractAutoProxyCreator类createProxy 方法。

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,			@Nullable Object[] specificInterceptors, TargetSource targetSource) {		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);		}		/**		 *  【1】创建代理工厂,赋值。		 */		ProxyFactory proxyFactory = new ProxyFactory();		proxyFactory.copyFrom(this);		/**		 * 【2】 proxyTargetClass为true时代表使用cglib,为false使用jdk,默认值是false。		 *  判断当前被代理对象是使用jdk增强还是使用cglib增强		 *		 */		if (!proxyFactory.isProxyTargetClass()) {			//根据最开始@EnableAspectJAutoProxy注解中的proxyTargetClass参数判断是否应该使用cglib代理			if (shouldProxyTargetClass(beanClass, beanName)) {				proxyFactory.setProxyTargetClass(true);			}			else {				//如果是接口增强那么使用jdk,否则使用cglib				evaluateProxyInterfaces(beanClass, proxyFactory);			}		}		//构建advisor		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);		//把advisor加入到代理工厂中		proxyFactory.addAdvisors(advisors);		//把targetSource对象加入代理工厂(实际对象、被代理对象)		proxyFactory.setTargetSource(targetSource);		customizeProxyFactory(proxyFactory);		proxyFactory.setFrozen(this.freezeProxy);		if (advisorsPreFiltered()) {			proxyFactory.setPreFiltered(true);		}		/**		 * 【3】 获取代理对象		 */		return proxyFactory.getProxy(getProxyClassLoader());	}
3.2 ProxyFactory 获取代理对象

描述: 先获取AOP代理

	public Object getProxy(@Nullable ClassLoader classLoader) {		/**		 *  创建AOP代理(JDK、CGLIB)并且获得代理对象		 */		return createAopProxy().getProxy(classLoader);	}
protected final synchronized AopProxy createAopProxy() {		if (!this.active) {			activate();		}		return getAopProxyFactory().createAopProxy(this);	}
@Override	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {			// 如果targetClass是接口类,使用JDK来生成Proxy			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);			}			// 如果不是接口类,使用CGLIB生成Proxy			return new ObjenesisCglibAopProxy(config);		}		else {			return new JdkDynamicAopProxy(config);		}	}
3.3 根据AOP不同的代理获取代理对象4 StudentDao 代理Debug

描述: 每个代理对象都对应一个代理工厂,工厂是new 创建的。

描述: 选择cglib、jdk代理生成代理对象。

描述: 创建AOP代理。

描述: CglibAopProxy获取代理对象。

描述: 获取到cglib增强代理对象。

5 StudentServiceImpl 代理Debug

描述: StudentServiceImpl 实现StudentService接口使用jdk代理。

描述: AOP获取JDK代理。

描述: 获取代理对象。

原文链接:

标签: #aop代理对象在什么时候创建