xml直接配置实现AOP
<aop:config>
<!--切点-->
<aop:pointcut id="schemaPointCut" expression="execution(void *..aop..*..test1(..))"/>
<!--切面-->
<aop:aspect id="schemaAspect" ref="schemaAspect">
<aop:before pointcut-ref="schemaPointCut" method="testBefore"/>
<aop:around pointcut="execution(void test2(..))" method="testAround"/>
<!--这个切点能匹配所有test3方法-->
<aop:after pointcut="execution(void test3(..))" method="testAfter"/>
</aop:aspect>
</aop:config>
注解方式实现
其中注解方式需要配置开启注解
-
xml配置注解生效:
<aop:aspectj-autoproxy> -
java配置注解生效
@EnableAspectJAutoProxy @Configuration public class AopConfig { }
开启后可以使用将如下类注册为bean进行切面配置
@Aspect
public class AnnotationAspect {
@Pointcut("execution(* *..aop..test1(..))")
public void aopBefore(){
}
@Before("aopBefore()")
public void before(){
System.out.println("before...");
}
@Around("execution(* test2(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before...");
Object o = pjp.proceed();
System.out.println("around after...");
return o;
}
@After("execution(* test3(..))")
public void after(){
System.out.println("after...");
}
}
AnnotationAwareAspectJAutoProxyCreator
以java配置注解生效为例,看看@EnableAspectJAutoProxy的作用,其实就是注册了一个Bean,AnnotationAwareAspectJAutoProxyCreator
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
// 注册 AnnotationAwareAspectJAutoProxyCreator
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 注解属性解析使用,代理机制和是否暴露代理
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
创建AOP代理
AnnotationAwareAspectJAutoProxyCreator继承结构图:
主要关心与Bean的创建直接相关的,BeanPostProcessor,猜测就是在这个生命周期的后置处理器中对bean进行对应切面中切点方法代理实现切面逻辑。
在其继承结构中的**AbstractAutoProxyCreator**中找到bean后置处理器初始化后和获得早期引用方法对其创建代理操作:(联想单例循环依赖的三级缓存)
// 存在循环依赖,早期引用创建即创建代理
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
this.earlyProxyReferences.add(cacheKey);
}
// 创建代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
// bean初始化后创建代理
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary方法内部调用创建代理:
// Create proxy if we have advice.
// 获得这个bean的拦截器信息/增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// bean类型,bean名称,拦截器信息,target bean原始传入进行创建
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
获得增强器过程
getAdvicesAndAdvisorsForBean,用于获得Advice与Advisors。
Advice
Advice是一个具体的切面方法执行策略,实现类有各种各样的拦截器,如子接口MethodInterceptor,也有不同的连接点joinpoint执行的不同策略实现子接口,如AfterAdvice等,注释中写了。
// 具体在子接口和实现类中定义
public interface Advice {
}
Advisor
Advisor接口定义了根据切点是否匹配,返回对应Advice,常见的重要的实现了如AOP事务的注解拦截器@Transactional实现TransactionAttributeSourceAdvisor,实现了异步执行方法的注解@Async实现AsyncAnnotationAdvisor等
public interface Advisor {
/**
* 可能是interceptor拦截器, a before advice切面方法前置处理, a throws advice, etc.
* 返回这个Advisor匹配上切点的Advice
* MethodInterceptor BeforeAdvice ThrowsAdvice AfterReturningAdvice等实现
*/
Advice getAdvice();
// 是否针对一个bean实例
boolean isPerInstance();
}
以上Advisor和Advice均由AOP创建代理实现,具体创建前拦截的配置获取阶段就是在这里了,由AbstractAdvisorAutoProxyCreator实现
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 找到针对本bean匹配的
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 扩展
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
// 被具体子类实现
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 获得Advisor.class类型的bean
return this.advisorRetrievalHelper.findAdvisorBeans();
}
其中findCandidateAdvisors在注解配置时又由AnnotationAwareAspectJAutoProxyCreator实现:
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 先使用父类获得Advisor.class类型的bean
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 再添加aspectJAdvisorsBuilder处理切面注解的类
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
@Aspect解析
aspectJAdvisorsBuilder.buildAspectJAdvisors()这个创建方法比较复杂,基本思路是:
遍历所有工厂内的bean,如果是Aspect类型,使用AspectJAdvisorFactory的getAdvisor方法解析出Advisor,单例的话直接放入缓存,非单例将getAdvisor的参数放入缓存。
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
其中getAdvisors方法由ReflectiveAspectJAdvisorFactory实现,顾名思义,就是要根据反射出的注解信息构建Advisors
// 遍历根据切面类型反射的方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 每个方法去构建Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
public Advisor getAdvisor() {
// 获得切点
AspectJExpressionPointcut expressionPointcut = getPointcut(..);
if (expressionPointcut == null) {
return null;
}
// 创建
return new InstantiationModelAwarePointcutAdvisorImpl(..);
}
Advisor创建
在InstantiationModelAwarePointcutAdvisorImpl方法内部,将完成切点的赋值,和advice的创建,即完成了一个Advisor的创建
public InstantiationModelAwarePointcutAdvisorImpl(..) {
//..赋值操作,切点,方法,切面名等
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// 懒加载,动态切点?
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 装配advice
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
Advice创建
instantiateAdvice方法创建最终的Advice,可能实现了方法拦截器之类的东西,在拦截器中调用这些advice:
// 根据方法注解类型,创建advice
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// 这个方法实现了方法拦截器,advice
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor ..{
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
}
寻找匹配的增强器
回到获得增强器之后的代码块,在AbstractAdvisorAutoProxyCreator中:
// 找到针对本bean匹配的
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
findAdvisorsThatCanApply 基本思路是,遍历获得到的增强器列表,判断加入列表,主要方法为canApply:
canApply(candidate, clazz);
//
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
// 切点匹配
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
// 目标类的相关类型,及接口
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
// 遍历,反射出所有方法,只要一个匹配即创建代理
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
分为IntroductionAdvisor,PointcutAdvisor两种类型,一种直接根据类过滤?,另一种根据切点是否匹配方法进行过滤。
得到所有适用于本bean的advisors后,按照可能有Order注解排序,返回,获得增强器过程结束。
使用增强器创建代理
回到创建AOP代理节的AbstractAutoProxyCreator类的wrapIfNecessary方法,如果advisors不为空,则执行创建代理方法createProxy:
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
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);
}
ProxyFactory proxyFactory = new ProxyFactory();
// 本身自己也是一个ProxyConfig,可以用来拷贝代理配置
proxyFactory.copyFrom(this);
// 根据目标代理类型设置
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 如果是创建jdk代理,获得其所有接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 封装增强器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 加入代理工厂
proxyFactory.addAdvisors(advisors);
// 设置代理目标类
proxyFactory.setTargetSource(targetSource);
// 留给子类机会自定义
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 创建获取
return proxyFactory.getProxy(getProxyClassLoader());
}
可以看出,createProxy方法主要用来创建ProxyFactory,给它设置各种属性,真正的代理就由它来创建。
封装增强器
获得到的Advisor无需处理,还可能获得到Advice,需要放在默认的切点Advisor中封装,DefaultPointcutAdvisor的切点直接为 Pointcut.TRUE。
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// 实现了方法拦截器,不需要适配器,直接封装
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
// 将Advice封装为Advisor时的默认切点为TRUE的Advisor
public DefaultPointcutAdvisor(Advice advice) {
this(Pointcut.TRUE, advice);
}
使用ProxyFactory创建代理
自适应决定创建代理类型,配置了激进代理策略/配置了使用类代理/没有任何用户接口,三种情况下,创建Cglib代理,否则创建JDK代理。
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 三种创建Cglib代理的情况
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);
}
}
getProxy方法定义在spring的AopProxy接口中,JdkDynamicAopProxy与ObjenesisCglibAopProxy各自实现。
JDK代理
回忆一下之前学过的jdk动态代理创建要素:
// 接口
// 接口实现类
// 实现InvocationHandler接口,将接口实现类对象放进去,覆盖方法
Object invoke(Proxy p, Method method, Object...args){}
// 使用Proxy静态方法返回,伪代码
Proxy.newInstance(ClassLoader cl, Class[] interfaces, new InvocationHandler())
JdkDynamicAopProxy直接实现了InvocationHandler接口,getProxy方法即像以前用过的一样套路:
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 创建代理,方法拦截就在本类中
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
主要来看看它的invoke方法如何实现:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Object retVal;
// 暴露上下文,给方法内调用使用
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 从advised(包含所有advisors和配置)中根据此方法创建一个链
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果对这个方法没有任何增强,直接调用目标类的即可
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 如果有增强,需要创建一个 反射方法调用ReflectiveMethodInvocation,进行调用
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// 返回
..
}
}
CGLIB代理
使用实例:
public class TestCGLIB {
void test(){
System.out.println("test");
}
// 不能继承的方法不能代理
final void test2(){
System.out.println("test2");
}
static void test3(){
System.out.println("test3");
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestCGLIB.class);
enhancer.setCallback(new MethodInterceptor() {
// 回调函数中,object为生成的继承代理对象,method为原方法,proxy为代理对象的方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(("before " + method));
Object re = proxy.invokeSuper(obj, args);
System.out.println(("after " + method));
return re;
}
});
TestCGLIB sub = (TestCGLIB) enhancer.create();
System.out.println(sub);
sub.test();
sub.test2();
sub.test3();
}
}
// 输出,其中toString,hashCode方法都会代理,toString时调用了hashCode(@...)
before public java.lang.String java.lang.Object.toString()
before public native int java.lang.Object.hashCode()
after public native int java.lang.Object.hashCode()
after public java.lang.String java.lang.Object.toString()
top.itlq.spring.core.aop.TestCGLIB$$EnhancerByCGLIB$$c10e68c3@5bb21b69
before void top.itlq.spring.core.aop.TestCGLIB.test()
test
after void top.itlq.spring.core.aop.TestCGLIB.test()
test2
test3
cglib库提供Enhancher,创建其对象new Enhancher,设置代理类setSuperClass,设置实现MethodInterceptor接口的方法拦截器,调用create()创建代理对象。
再来看ObjenesisCglibAopProxy如何使用CGLIB创建的代理,实现的增强,继承了CglibAopProxy,核心在其中getProxy实现:
public Object getProxy(@Nullable ClassLoader classLoader) {
..
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 核心,获得回调
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
..
}
在getCallbacks方法创建了拦截器数组,其中包括包含advisors的DynamicAdvisedInterceptor:
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
DynamicAdvisedInterceptor继承自CGLIB的方法拦截器MethodInteceptor,它的invoke方法逻辑基本与JDK代理的invoke方法一致:
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//..
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果链空,直接调用,调的也是继承方法,因为只有继承对象
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
// 创建类似前面ReflectiveMethodInvocation的CglibMethodInvocation
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
}
其中不同的地方为方法调用部分使用了CglibMethodInvocation,它其实继承了前面的ReflectiveMethodInvocation且核心的proceed方法没有改写。
private static class CglibMethodInvocation extends ReflectiveMethodInvocation{}
总结
主要写的东西和过程:
- xml和注解配置使用AOP,切点,切面,增强等概念和配置
- 注解配置的开启原理,AnnotationAwareAspectAutoProxyCreator,作为一个BeanPosProcessor在加载bean的时候,早期引用/初始化完成阶段创建决定是否创建代理。
- 创建代理的过程,获得Advisor增强器,通过Advisor类型和@Aspect注解解析,根据bean的方法是否匹配增强器决定是否用来创建代理。使用ProxyFactor创建代理,可能是JDK代理,可能是CGLIB代理。
- 在代理的方法调用拦截中,根据切点匹配advisors,并把他们组成一各ReflectiveMethodInvocation链,执行拦截器。