就像IOC底层的实现依靠的是BeanWrapper,Convert,PropertyEditor这些基础设施类一样,AOP的实现底层也依赖了这样一批基础类,下面我们来看看。
AopInfrastructureBean是一个标记接口。若Bean实现了此接口,表明它是一个Spring AOP的基础类,那么这个类是不会被AOP给代理的,即使它能被切面切进去~~~
public interface AopInfrastructureBean {
}
用于创建代理的配置的父类,以确保所有代理创建者具有一致的属性。 它有五个属性,解释如下:
public class ProxyConfig implements Serializable {
// 标记是否直接对目标类进行代理,而不是通过接口产生代理
private boolean proxyTargetClass = false;
// 标记是否对代理进行优化。true:那么在生成代理对象之后,如果对代理配置进行了修改,已经创建的代理对象也不会获取修改之后的代理配置。
// 如果exposeProxy设置为true,即使optimize为true也会被忽略。
private boolean optimize = false;
// 标记是否需要阻止通过该配置创建的代理对象转换为Advised类型,默认值为false,表示代理对象可以被转换为Advised类型
//Advised接口其实就代表了被代理的对象(此接口是Spring AOP提供,它提供了方法可以对代理进行操作,比如移除一个切面之类的),它持有了代理对象的一些属性,通过它可以对生成的代理对象的一些属性进行人为干预
// 默认情况,我们可以这么完 Advised target = (Advised) context.getBean("opaqueTest"); 从而就可以对该代理持有的一些属性进行干预勒 若此值为true,就不能这么玩了
boolean opaque = false;
//标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
//当一个代理对象需要调用它【自己】的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
//实践场景:如何让被代理的方法在代理对象被代理的方法中被调用时,依旧能被拦截
boolean exposeProxy = false;
//标记是否需要冻结代理对象,即在代理对象生成之后,是否允许对其进行修改,默认为false.
// 当我们不希望调用方修改转换成Advised对象之后的代理对象时,就可以设置为true 给冻结上即可
private boolean frozen = false;
...
}
简单的说它就是提供为代理创建器提供了一些公共方法实现:
具有代理处理器通用功能的基类,特别是 ClassLoader 管理和 evaluateProxyInterfaces 算法。
@SuppressWarnings("serial")
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
/**
AOP的自动代理创建器必须在所有的别的processors之后执行,以确保它可以代理到所有的小伙伴们,即使需要双重代理得那种
*/
private int order = Ordered.LOWEST_PRECEDENCE;
//代理类的类加载器
@Nullable
private ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
//代理类的类加载器是否被手动配置了---即用户是否手动指定了类加载器
private boolean classLoaderConfigured = false;
/**
Set the ordering which will apply to this processor's implementation of Ordered,
used when applying multiple processors.
The default value is Ordered.LOWEST_PRECEDENCE, meaning non-ordered.
*/
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
/**
手动设置代理类加载器
*/
public void setProxyClassLoader(@Nullable ClassLoader classLoader) {
this.proxyClassLoader = classLoader;
//如果不为空,说明手动设置生效,打个标记
this.classLoaderConfigured = (classLoader != null);
}
@Nullable
protected ClassLoader getProxyClassLoader() {
return this.proxyClassLoader;
}
//因为继承了BeanClassLoaderAware,因此默认的代理类加载器就是beanFactory用来加载所有bean的beanClassLoader
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
//手动配置的优先级更高,无法覆盖
if (!this.classLoaderConfigured) {
this.proxyClassLoader = classLoader;
}
}
/**
* Check the interfaces on the given bean class and apply them to the link ProxyFactory
* if appropriate.
* 检查给定类上的所有接口,然后检查分析决定代理方式
*/
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
//拿到目标类上的所有接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
//是否存在合理的接口---可以决定是否采用jdk动态代理,如果为false则走cglib动态代理
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
if (
//pass内部的回调接口
!isConfigurationCallbackInterface(ifc) &&
//pass内部语言接口
!isInternalLanguageInterface(ifc) &&
//当前接口内是否存在方法
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
//如果存在合理的接口
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
// 这里Spring的Doc特别强调了:不能值只把合理的接口设置进去,而是都得加入进去
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 这个很明显设置true,表示使用CGLIB得方式去创建代理了~~~~
//proxyFactory继承了proxyConfig,这里调用的是proxyConfig的setProxyTargetClass方法
proxyFactory.setProxyTargetClass(true);
}
}
/**
判断此接口类型是否属于:容器去回调的类型,这里例举处理一些接口 初始化、销毁、自动刷新、自动关闭、Aware感知等等
*/
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
/**
是否是如下通用的接口。若实现的是这些接口也会排除,不认为它是实现了接口的类
*/
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
}
/**
用于在代理后面公开目标类的最小接口。
由 AOP 代理对象和代理工厂(通过 org.springframework.aop.framework.Advised)以及 TargetSources 实现。
*/
public interface TargetClassAware {
@Nullable
Class<?> getTargetClass();
}
Spring官方英文注释:
简单解释:
该接口用于保存一个代理的相关配置。比如保存了这个代理相关的拦截器、通知、增强器等等。
所有的代理对象都实现了该接口(我们就能够通过一个代理对象获取这个代理对象怎么被代理出来的相关信息)
不管是JDKproxy,还是cglib proxy,代理出来的对象都实现了org.springframework.aop.framework.Advised接口;
/**
* Interface to be implemented by classes that hold the configuration
* of a factory of AOP proxies. This configuration includes the
* Interceptors and other advice, Advisors, and the proxied interfaces.
*
* <p>Any AOP proxy obtained from Spring can be cast to this interface to
* allow manipulation of its AOP advice.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 13.03.2003
* @see org.springframework.aop.framework.AdvisedSupport
*/
public interface Advised extends TargetClassAware {
/**
* Return whether the Advised configuration is frozen,
* in which case no advice changes can be made.
*/
boolean isFrozen();
/**
* Are we proxying the full target class instead of specified interfaces?
*/
boolean isProxyTargetClass();
/**
* Return the interfaces proxied by the AOP proxy.
* <p>Will not include the target class, which may also be proxied.
*/
Class<?>[] getProxiedInterfaces();
/**
* Determine whether the given interface is proxied.
*/
boolean isInterfaceProxied(Class<?> intf);
/**
Change the TargetSource used by this Advised object.
Only works if the configuration isn't frozen.
*/
void setTargetSource(TargetSource targetSource);
/**
* Return the {@code TargetSource} used by this {@code Advised} object.
*/
TargetSource getTargetSource();
/**
设置代理是否应由 AOP 框架公开为 ThreadLocal 以通过 AopContext 类进行获取
It can be necessary to expose the proxy if an advised object needs to
invoke a method on itself with advice applied. Otherwise,
if an advised object invokes a method on this, no advice will be applied.
Default is false, for optimal performance.
*/
void setExposeProxy(boolean exposeProxy);
/**
* Return whether the factory should expose the proxy as a ThreadLocal.
* It can be necessary to expose the proxy if an advised object needs
* to invoke a method on itself with advice applied. Otherwise, if an
* advised object invokes a method on this, no advice will be applied.
* @see AopContext
*/
boolean isExposeProxy();
/**
设置是否预过滤此代理配置,使其仅包含适用的advisors(匹配此代理的目标类)
默认为“假”。如果advisors已经被预先过滤,则将此设置为“true”,这意味着在为代理调用构建实际advisors链时可以跳过 ClassFilter 检查。
*/
void setPreFiltered(boolean preFiltered);
/**
* Return whether this proxy configuration is pre-filtered so that it only
* contains applicable advisors (matching this proxy's target class).
*/
boolean isPreFiltered();
//操作当前代理对象advisors的相关方法
Advisor[] getAdvisors();
default int getAdvisorCount() {
return getAdvisors().length;
}
void addAdvisor(Advisor advisor) throws AopConfigException;
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
boolean removeAdvisor(Advisor advisor);
void removeAdvisor(int index) throws AopConfigException;
int indexOf(Advisor advisor);
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
//操作当前代理对象advice的相关方法
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice) throws AopConfigException;
boolean removeAdvice(Advice advice);
int indexOf(Advice advice);
String toProxyConfigString();
}
它最重要的一个方法是:提供getInterceptorsAndDynamicInterceptionAdvice方法用来获取对应代理方法对应有效的拦截器链
AdvisedSupport本身不会提供创建代理的任何方法,专注于生成拦截器链。委托给ProxyCreatorSupport去创建代理对象
public class AdvisedSupport extends ProxyConfig implements Advised {
private static final long serialVersionUID = 2651364800145442165L;
/**
* Canonical TargetSource when there's no target, and behavior is
* supplied by the advisors.
*/
public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
/** Package-protected to allow direct access for efficiency. */
TargetSource targetSource = EMPTY_TARGET_SOURCE;
/** Whether the Advisors are already filtered for the specific target class. */
private boolean preFiltered = false;
/**生产当前方法关联的拦截器链集合*/
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
/** Cache with Method as key and advisor chain List as value. */
private transient Map<MethodCacheKey, List<Object>> methodCache;
/**
* Interfaces to be implemented by the proxy. Held in List to keep the order
* of registration, to create JDK proxy with specified order of interfaces.
* 代理类需要继承的接口
*/
private List<Class<?>> interfaces = new ArrayList<>();
/**
* List of Advisors. If an Advice is added, it will be wrapped
* in an Advisor before being added to this List.
*/
private List<Advisor> advisors = new ArrayList<>();
/**
该方法是该类中最重要的一个方法,因此我把他移动到了最前面
* Determine a list of MethodInterceptor objects
* for the given method, based on this configuration.
* 获取当前方法对应的拦截器链
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
//先构造缓存key
MethodCacheKey cacheKey = new MethodCacheKey(method);
//先看缓存中是否存在
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
//缓存中没有,再通过advisorChainFactory得到当前方法关联的拦截器链,放入缓存中
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
/**
* No-arg constructor for use as a JavaBean.
*/
public AdvisedSupport() {
this.methodCache = new ConcurrentHashMap<>(32);
}
/**
* Create a AdvisedSupport instance with the given parameters.
*/
public AdvisedSupport(Class<?>... interfaces) {
this();
setInterfaces(interfaces);
}
/**
* Set the given object as target.
* Will create a SingletonTargetSource for the object.
*/
public void setTarget(Object target) {
//所有的目标对象都会被包装为TargetSource---默认为SingletonTargetSource
setTargetSource(new SingletonTargetSource(target));
}
@Override
public void setTargetSource(@Nullable TargetSource targetSource) {
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}
@Override
public TargetSource getTargetSource() {
return this.targetSource;
}
public void setTargetClass(@Nullable Class<?> targetClass) {
this.targetSource = EmptyTargetSource.forClass(targetClass);
}
@Override
@Nullable
public Class<?> getTargetClass() {
return this.targetSource.getTargetClass();
}
@Override
public void setPreFiltered(boolean preFiltered) {
this.preFiltered = preFiltered;
}
@Override
public boolean isPreFiltered() {
return this.preFiltered;
}
/**
* Set the advisor chain factory to use.
*/
public void setAdvisorChainFactory(AdvisorChainFactory advisorChainFactory) {
Assert.notNull(advisorChainFactory, "AdvisorChainFactory must not be null");
this.advisorChainFactory = advisorChainFactory;
}
/**
* Return the advisor chain factory to use (never {@code null}).
*/
public AdvisorChainFactory getAdvisorChainFactory() {
return this.advisorChainFactory;
}
/**
* Set the interfaces to be proxied.
*/
public void setInterfaces(Class<?>... interfaces) {
Assert.notNull(interfaces, "Interfaces must not be null");
this.interfaces.clear();
for (Class<?> ifc : interfaces) {
addInterface(ifc);
}
}
/**
* Add a new proxied interface.
*/
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();
}
}
public boolean removeInterface(Class<?> intf) {
return this.interfaces.remove(intf);
}
@Override
public Class<?>[] getProxiedInterfaces() {
return ClassUtils.toClassArray(this.interfaces);
}
//当前接口是否被代理了
@Override
public boolean isInterfaceProxied(Class<?> intf) {
for (Class<?> proxyIntf : this.interfaces) {
if (intf.isAssignableFrom(proxyIntf)) {
return true;
}
}
return false;
}
@Override
public final Advisor[] getAdvisors() {
return this.advisors.toArray(new Advisor[0]);
}
@Override
public int getAdvisorCount() {
return this.advisors.size();
}
@Override
public void addAdvisor(Advisor advisor) {
int pos = this.advisors.size();
addAdvisor(pos, advisor);
}
@Override
public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
if (advisor instanceof IntroductionAdvisor) {
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
}
addAdvisorInternal(pos, advisor);
}
@Override
public boolean removeAdvisor(Advisor advisor) {
int index = indexOf(advisor);
if (index == -1) {
return false;
}
else {
removeAdvisor(index);
return true;
}
}
@Override
public void removeAdvisor(int index) throws AopConfigException {
if (isFrozen()) {
throw new AopConfigException("Cannot remove Advisor: Configuration is frozen.");
}
if (index < 0 || index > this.advisors.size() - 1) {
throw new AopConfigException("Advisor index " + index + " is out of bounds: " +
"This configuration only has " + this.advisors.size() + " advisors.");
}
Advisor advisor = this.advisors.remove(index);
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
// We need to remove introduction interfaces.
for (Class<?> ifc : ia.getInterfaces()) {
removeInterface(ifc);
}
}
adviceChanged();
}
@Override
public int indexOf(Advisor advisor) {
Assert.notNull(advisor, "Advisor must not be null");
return this.advisors.indexOf(advisor);
}
@Override
public boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException {
Assert.notNull(a, "Advisor a must not be null");
Assert.notNull(b, "Advisor b must not be null");
int index = indexOf(a);
if (index == -1) {
return false;
}
removeAdvisor(index);
addAdvisor(index, b);
return true;
}
/**
* Add all of the given advisors to this proxy configuration.
* @param advisors the advisors to register
*/
public void addAdvisors(Advisor... advisors) {
addAdvisors(Arrays.asList(advisors));
}
/**
* Add all of the given advisors to this proxy configuration.
* @param advisors the advisors to register
*/
public void addAdvisors(Collection<Advisor> advisors) {
if (isFrozen()) {
throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
}
if (!CollectionUtils.isEmpty(advisors)) {
for (Advisor advisor : advisors) {
if (advisor instanceof IntroductionAdvisor) {
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
}
Assert.notNull(advisor, "Advisor must not be null");
this.advisors.add(advisor);
}
adviceChanged();
}
}
private void validateIntroductionAdvisor(IntroductionAdvisor advisor) {
advisor.validateInterfaces();
// If the advisor passed validation, we can make the change.
Class<?>[] ifcs = advisor.getInterfaces();
for (Class<?> ifc : ifcs) {
addInterface(ifc);
}
}
private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
Assert.notNull(advisor, "Advisor must not be null");
if (isFrozen()) {
throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
}
if (pos > this.advisors.size()) {
throw new IllegalArgumentException(
"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
}
this.advisors.add(pos, advisor);
adviceChanged();
}
/**
* Allows uncontrolled access to the {@link List} of {@link Advisor Advisors}.
* Use with care, and remember to {@link #adviceChanged() fire advice changed events}
* when making any modifications.
*/
protected final List<Advisor> getAdvisorsInternal() {
return this.advisors;
}
@Override
public void addAdvice(Advice advice) throws AopConfigException {
int pos = this.advisors.size();
addAdvice(pos, advice);
}
/**
* Cannot add introductions this way unless the advice implements IntroductionInfo.
*/
@Override
public void addAdvice(int pos, Advice advice) throws AopConfigException {
Assert.notNull(advice, "Advice must not be null");
if (advice instanceof IntroductionInfo) {
// We don't need an IntroductionAdvisor for this kind of introduction:
// It's fully self-describing.
addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
}
else if (advice instanceof DynamicIntroductionAdvice) {
// We need an IntroductionAdvisor for this kind of introduction.
throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
}
else {
addAdvisor(pos, new DefaultPointcutAdvisor(advice));
}
}
@Override
public boolean removeAdvice(Advice advice) throws AopConfigException {
int index = indexOf(advice);
if (index == -1) {
return false;
}
else {
removeAdvisor(index);
return true;
}
}
@Override
public int indexOf(Advice advice) {
Assert.notNull(advice, "Advice must not be null");
for (int i = 0; i < this.advisors.size(); i++) {
Advisor advisor = this.advisors.get(i);
if (advisor.getAdvice() == advice) {
return i;
}
}
return -1;
}
/**
* Is the given advice included in any advisor within this proxy configuration?
*/
public boolean adviceIncluded(@Nullable Advice advice) {
if (advice != null) {
for (Advisor advisor : this.advisors) {
if (advisor.getAdvice() == advice) {
return true;
}
}
}
return false;
}
/**
* Count advices of the given class.
*/
public int countAdvicesOfType(@Nullable Class<?> adviceClass) {
int count = 0;
if (adviceClass != null) {
for (Advisor advisor : this.advisors) {
if (adviceClass.isInstance(advisor.getAdvice())) {
count++;
}
}
}
return count;
}
/**
* 新增加了一个adivce,那么缓存就失效了,因为对应方法的拦截器链可能发生的变化
*/
protected void adviceChanged() {
this.methodCache.clear();
}
//...忽略不重要的方法
/**
* Simple wrapper class around a Method. Used as the key when
* caching methods, for efficient equals and hashCode comparisons.
* 用于缓存当前方法和对应方法关联拦截器链的方法缓存key
*/
private static final class MethodCacheKey implements Comparable<MethodCacheKey> {
private final Method method;
private final int hashCode;
public MethodCacheKey(Method method) {
this.method = method;
this.hashCode = method.hashCode();
}
...
}
}
public interface AdvisorChainFactory {
/**
Determine a list of MethodInterceptors for the given advisor chain configuration.
*/
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);
}
该类只有一个默认实现
A simple but definitive way of working out an advice chain for a Method, given an Advised object. Always rebuilds each advice chain; caching can be provided by subclasses.
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
//AdvisorAdapterRegistry负责将advisor转换为MethodInterceptor
//GlobalAdvisorAdapterRegistry获取到的是全局共享的AdvisorAdapterRegistry,下面会讲到
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//获取应用到当前代理类上的所有增强器
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
//处理PointcutAdvisor
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
//利用registry将advisor转换为MethodInterceptor[]
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//处理IntroductionAdvisor
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
//利用registry将advisor转换为MethodInterceptor[]
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
//处理其他advisor
else {
//利用registry将advisor转换为MethodInterceptor[]
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
/**
* Determine whether the Advisors contain matching introductions.
*/
private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
for (Advisor advisor : advisors) {
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
//IntroductionAdvisor只实现了类级别的过滤
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
}
return false;
}
}
该类主要作用是从AdvisedSupport获取到当前代理对象上应用的advisors集合,然后将这些advisors集合转换为一组methodInterceptor返回
spring aop框架对BeforeAdvice、AfterAdvice、ThrowsAdvice三种通知类型的支持实际上是借助适配器模式来实现的,这样的好处是使得框架允许用户向框架中加入自己想要支持的任何一种通知类型
AdvisorAdapter是一个适配器接口,它定义了自己支持的Advice类型,并且能把一个Advisor适配成MethodInterceptor,以下是它的定义
public interface AdvisorAdapter {
// 判断此适配器是否支持特定的Advice
boolean supportsAdvice(Advice advice);
// 将一个Advisor适配成MethodInterceptor
MethodInterceptor getInterceptor(Advisor advisor);
}
一般我们自己并不需要自己去提供此接口的实现,因为Spring为我们提供了对应的实现:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
AdvisorAdapter注册表的接口。这是一个 SPI 接口,任何 Spring 用户都不能实现。
public interface AdvisorAdapterRegistry {
//advice适配为Advisor
Advisor wrap(Object advice) throws UnknownAdviceTypeException;
//advisor适配为MethodInterceptor[]
MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException;
//注册AdvisorAdapter
void registerAdvisorAdapter(AdvisorAdapter adapter);
}
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* 注册三个默认的适配器
*/
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
//advice适配为advisor后返回
@Override
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);
}
//advisor适配为MethodInterceptor[]
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
//如果本身就是MethodInterceptor,那就不需要进行适配,直接加入集合
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//AdvisorAdapter转换的都是本身并不是MethodInterceptor的advisor
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
//一个advisor转换为一个MethodInterceptor
return interceptors.toArray(new MethodInterceptor[0]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
如果我们想把自己定义的AdvisorAdapter注册到spring aop框架中,怎么办?
public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {
//获取到全局唯一共享的DefaultAdvisorAdapterRegistry
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
/**
* Specify the AdvisorAdapterRegistry to register AdvisorAdapter beans with.
* Default is the global AdvisorAdapterRegistry.
*/
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AdvisorAdapter){
this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);
}
return bean;
}
}
Singleton 发布一个共享的 DefaultAdvisorAdapterRegistry 实例。
public final class GlobalAdvisorAdapterRegistry {
private GlobalAdvisorAdapterRegistry() {
}
/**
* Keep track of a single instance so we can return it to classes that request it.
*/
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
/**
* Return the singleton {@link DefaultAdvisorAdapterRegistry} instance.
*/
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
/**
* Reset the singleton {@link DefaultAdvisorAdapterRegistry}, removing any
* {@link AdvisorAdapterRegistry#registerAdvisorAdapter(AdvisorAdapter) registered}
* adapters.
*/
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}
}
DefaultAdvisorChainFactory中就会用到这个类,来获取全局共享的DefaultAdvisorAdapterRegistry 实例
所有的Aop代理对象或者代理工厂(proxy factory)都要实现的接口,该接口用于暴露出被代理目标对象类型;
public interface TargetClassAware {
@Nullable
Class<?> getTargetClass();
}
该接口代表一个目标对象,在aop调用目标对象的时候,使用该接口返回真实的对象。
比如它有其中两个实现SingletonTargetSource和PrototypeTargetSource代表着每次调用返回同一个实例,和每次调用返回一个新的实例
public interface TargetSource extends TargetClassAware {
@Override
@Nullable
Class<?> getTargetClass();
/**
所有对 getTarget() 的调用都会返回相同的对象吗?
这种情况下,就不需要调用releaseTarget(Object)了,AOP框架可以缓存getTarget()的返回值。
单例可缓存
*/
boolean isStatic();
/**
Return a target instance.
Invoked immediately before the AOP framework calls the "target" of an AOP method invocation.
*/
@Nullable
Object getTarget() throws Exception;
/**
* Release the given target object obtained from the method, if any.
*/
void releaseTarget(Object target) throws Exception;
}
public class AspectMetadata implements Serializable {
private final String aspectName;
private final Class<?> aspectClass;
// AjType这个字段非常的关键,它表示有非常非常多得关于这个切面的一些数据、方法(位于org.aspectj下)
private transient AjType<?> ajType;
// 解析切入点表达式用的,但是真正的解析工作为委托给`org.aspectj.weaver.tools.PointcutExpression`来解析的
//若是单例:则是Pointcut.TRUE 否则为AspectJExpressionPointcut
private final Pointcut perClausePointcut;
public AspectMetadata(Class<?> aspectClass, String aspectName) {
this.aspectName = aspectName;
Class<?> currClass = aspectClass;
AjType<?> ajType = null;
// 此处会一直遍历到顶层知道Object 直到找到有一个是Aspect切面就行,然后保存起来
// 因此我们的切面写在父类上 也是欧克的
while (currClass != Object.class) {
AjType<?> ajTypeToCheck = AjTypeSystem.getAjType(currClass);
if (ajTypeToCheck.isAspect()) {
ajType = ajTypeToCheck;
break;
}
currClass = currClass.getSuperclass();
}
// 由此可见,我们传进来的Class必须是个切面或者切面的子类的~~~
if (ajType == null) {
throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
}
// 显然Spring AOP目前也不支持优先级的声明。。。
if (ajType.getDeclarePrecedence().length > 0) {
throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
}
this.aspectClass = ajType.getJavaClass();
this.ajType = ajType;
// 切面的处在类型:PerClauseKind 由此可议看出,Spring的AOP目前只支持下面4种
switch (this.ajType.getPerClause().getKind()) {
case SINGLETON:
// 如国是单例,这个表达式返回这个常量
this.perClausePointcut = Pointcut.TRUE;
return;
case PERTARGET:
case PERTHIS:
// PERTARGET和PERTHIS处理方式一样 返回的是AspectJExpressionPointcut
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setLocation(aspectClass.getName());
//设置好 切点表达式
ajexp.setExpression(findPerClause(aspectClass));
ajexp.setPointcutDeclarationScope(aspectClass);
this.perClausePointcut = ajexp;
return;
case PERTYPEWITHIN:
// Works with a type pattern
// 组成的、合成得切点表达式~~~
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
return;
default:
// 其余的Spring AOP暂时不支持
throw new AopConfigException(
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
}
}
private String findPerClause(Class<?> aspectClass) {
String str = aspectClass.getAnnotation(Aspect.class).value();
str = str.substring(str.indexOf('(') + 1);
str = str.substring(0, str.length() - 1);
return str;
}
...
public Pointcut getPerClausePointcut() {
return this.perClausePointcut;
}
// 判断perThis或者perTarger,最单实例、多实例处理
public boolean isPerThisOrPerTarget() {
PerClauseKind kind = getAjType().getPerClause().getKind();
return (kind == PerClauseKind.PERTARGET || kind == PerClauseKind.PERTHIS);
}
// 是否是within的
public boolean isPerTypeWithin() {
PerClauseKind kind = getAjType().getPerClause().getKind();
return (kind == PerClauseKind.PERTYPEWITHIN);
}
// 只要不是单例的,就都属于Lazy懒加载,延迟实例化的类型~~~~
public boolean isLazilyInstantiated() {
return (isPerThisOrPerTarget() || isPerTypeWithin());
}
}
Spring AOP支持AspectJ的singleton、perthis、pertarget、pertypewithin实例化模型(目前不支持percflow、percflowbelow) 参见枚举类PerClauseKind
默认是singleton实例化模型,Schema风格只支持singleton实例化模型,而@AspectJ风格支持这三种实例化模型
singleton:使用@Aspect()指定,即默认就是单例实例化模式,在此就不演示示例了
perthis:每个切入点表达式匹配的连接点对应的AOP代理对象都会创建一个新的切面实例,使用@Aspect(“perthis(切入点表达式)”)指定切入点表达式;
// 他将为每个被切入点表达式匹配上的代理对象,都创建一个新的切面实例(此处允许HelloService是接口)
@Aspect("perthis(this(com.fsx.HelloService))")
pertarget:每个切入点表达式匹配的连接点对应的目标对象都会创建一个新的切面实例,使用@Aspect(“pertarget(切入点表达式)”)指定切入点表达式; 此处要求HelloService不能是接口
另外需要注意一点:若在Spring内要使用perthis和pertarget,请把切面的Scope定义为:prototype
专门为切面创建实例的工厂(因为切面也不一定是单例的,也支持各种多例形式。上面已有说明)
// 它实现了Order接口哦~~~~支持排序的
public interface AspectInstanceFactory extends Ordered {
//Create an instance of this factory's aspect.
Object getAspectInstance();
//Expose the aspect class loader that this factory uses.
@Nullable
ClassLoader getAspectClassLoader();
}
它的实现类如下:
SimpleAspectInstanceFactory:根据切面的aspectClass,调用空构造函数反射.newInstance()创建一个实例(备注:构造函数private的也没有关系)
SingletonAspectInstanceFactory:这个就更简单了,因为已经持有aspectInstance得引用了,直接return即可
AspectInstanceFactory的子接口。提供了获取AspectMetadata的方法
public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactory {
/**
* Return the AspectJ AspectMetadata for this factory's aspect.
*/
AspectMetadata getAspectMetadata();
/**
* Return the best possible creation mutex for this factory.
*/
@Nullable
Object getAspectCreationMutex();
}
SimpleMetadataAwareAspectInstanceFactory和SingletonMetadataAwareAspectInstanceFactory已经直接关联到AspectMetadata,所以直接return即可。
LazySingletonAspectInstanceFactoryDecorator也只是个简单的装饰而已。
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory, Serializable {
// 持有对Bean工厂的引用
private final BeanFactory beanFactory;
// 需要处理的名称
private final String name;
private final AspectMetadata aspectMetadata;
// 传了Name,type可议不传,内部判断出来
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
this(beanFactory, name, null);
}
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, @Nullable Class<?> type) {
this.beanFactory = beanFactory;
this.name = name;
Class<?> resolvedType = type;
// 若没传type,就去Bean工厂里看看它的Type是啥 type不能为null~~~~
if (type == null) {
resolvedType = beanFactory.getType(name);
Assert.notNull(resolvedType, "Unresolvable bean type - explicitly specify the aspect class");
}
// 包装成切面元数据类
this.aspectMetadata = new AspectMetadata(resolvedType, name);
}
// 此处:切面实例 是从Bean工厂里获取的 需要注意
// 若是多例的,请注意Scope的值
@Override
public Object getAspectInstance() {
return this.beanFactory.getBean(this.name);
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
}
@Override
public AspectMetadata getAspectMetadata() {
return this.aspectMetadata;
}
@Override
@Nullable
public Object getAspectCreationMutex() {
if (this.beanFactory.isSingleton(this.name)) {
// Rely on singleton semantics provided by the factory -> no local lock.
return null;
}
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
// No singleton guarantees from the factory -> let's lock locally but
// reuse the factory's singleton lock, just in case a lazy dependency
// of our advice bean happens to trigger the singleton lock implicitly...
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
}
else {
return this;
}
}
@Override
public int getOrder() {
Class<?> type = this.beanFactory.getType(this.name);
if (type != null) {
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
}
// 若没实现接口,就拿注解的值
return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE);
}
return Ordered.LOWEST_PRECEDENCE;
}
}
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory implements Serializable {
public PrototypeAspectInstanceFactory(BeanFactory beanFactory, String name) {
super(beanFactory, name);
// 若不是多例,直接报错了
if (!beanFactory.isPrototype(name)) {
throw new IllegalArgumentException(
"Cannot use PrototypeAspectInstanceFactory with bean named '" + name + "': not a prototype");
}
}
}
下面介绍下aspectj这个jar包下几个重要的类
public class AjTypeSystem {
// 每个切面都给缓存上 注意:此处使用的是WeakReference 一定程度上节约内存
private static Map<Class, WeakReference<AjType>> ajTypes =
Collections.synchronizedMap(new WeakHashMap<Class,WeakReference<AjType>>());
public static <T> AjType<T> getAjType(Class<T> fromClass) {
WeakReference<AjType> weakRefToAjType = ajTypes.get(fromClass);
if (weakRefToAjType!=null) {
AjType<T> theAjType = weakRefToAjType.get();
if (theAjType != null) {
return theAjType;
} else {
// 其实只有这一步操作:new AjTypeImpl~~~ AjTypeImpl就相当于代理了Class的很多事情~~~~
theAjType = new AjTypeImpl<T>(fromClass);
ajTypes.put(fromClass, new WeakReference<AjType>(theAjType));
return theAjType;
}
}
// neither key nor value was found
AjType<T> theAjType = new AjTypeImpl<T>(fromClass);
ajTypes.put(fromClass, new WeakReference<AjType>(theAjType));
return theAjType;
}
}
// 它继承自Java得Type和AnnotatedElement 它自己还提供了非常非常多的方法,基本都是获取元数据的一些方法,等到具体使用到的时候再来看也可以
public interface AjType<T> extends Type, AnnotatedElement {
...
}
AjTypeImpl是AjType的唯一实现类,因为方法实在是太多了,因此下面我只展示一些觉得比较有意思的方法实现:
public class AjTypeImpl<T> implements AjType<T> {
private static final String ajcMagic = "ajc$";
// 它真正传进来的,只是这个class,它是一个标注了@Aspect注解的Class类
private Class<T> clazz;
private Pointcut[] declaredPointcuts = null;
private Pointcut[] pointcuts = null;
private Advice[] declaredAdvice = null;
private Advice[] advice = null;
private InterTypeMethodDeclaration[] declaredITDMethods = null;
private InterTypeMethodDeclaration[] itdMethods = null;
private InterTypeFieldDeclaration[] declaredITDFields = null;
private InterTypeFieldDeclaration[] itdFields = null;
private InterTypeConstructorDeclaration[] itdCons = null;
private InterTypeConstructorDeclaration[] declaredITDCons = null;
// 唯一的一个构造函数
public AjTypeImpl(Class<T> fromClass) {
this.clazz = fromClass;
}
// 这个方法有意思的地方在于:它把所有的接口类,都变成AjType类型了
public AjType<?>[] getInterfaces() {
Class<?>[] baseInterfaces = clazz.getInterfaces();
return toAjTypeArray(baseInterfaces);
}
private AjType<?>[] toAjTypeArray(Class<?>[] classes) {
AjType<?>[] ajtypes = new AjType<?>[classes.length];
for (int i = 0; i < ajtypes.length; i++) {
ajtypes[i] = AjTypeSystem.getAjType(classes[i]);
}
return ajtypes;
}
// 就是把clazz返回出去
public Class<T> getJavaClass() {
return clazz;
}
public AjType<? super T> getSupertype() {
Class<? super T> superclass = clazz.getSuperclass();
return superclass==null ? null : (AjType<? super T>) new AjTypeImpl(superclass);
}
// 判断是否是切面,就看是否有这个注解~~
public boolean isAspect() {
return clazz.getAnnotation(Aspect.class) != null;
}
// 这个方法很重要:PerClause AspectJ切面的表现形式
// 备注:虽然有这么多(参考这个类PerClauseKind),但是Spring AOP只支持前三种~~~
public PerClause getPerClause() {
if (isAspect()) {
Aspect aspectAnn = clazz.getAnnotation(Aspect.class);
String perClause = aspectAnn.value();
if (perClause.equals("")) {
// 如果自己没写,但是存在父类的话并且父类是切面,那就以父类的为准~~~~
if (getSupertype().isAspect()) {
return getSupertype().getPerClause();
}
// 不写默认是单例的,下面的就不一一解释了
return new PerClauseImpl(PerClauseKind.SINGLETON);
} else if (perClause.startsWith("perthis(")) {
return new PointcutBasedPerClauseImpl(PerClauseKind.PERTHIS,perClause.substring("perthis(".length(),perClause.length() - 1));
} else if (perClause.startsWith("pertarget(")) {
return new PointcutBasedPerClauseImpl(PerClauseKind.PERTARGET,perClause.substring("pertarget(".length(),perClause.length() - 1));
} else if (perClause.startsWith("percflow(")) {
return new PointcutBasedPerClauseImpl(PerClauseKind.PERCFLOW,perClause.substring("percflow(".length(),perClause.length() - 1));
} else if (perClause.startsWith("percflowbelow(")) {
return new PointcutBasedPerClauseImpl(PerClauseKind.PERCFLOWBELOW,perClause.substring("percflowbelow(".length(),perClause.length() - 1));
} else if (perClause.startsWith("pertypewithin")) {
return new TypePatternBasedPerClauseImpl(PerClauseKind.PERTYPEWITHIN,perClause.substring("pertypewithin(".length(),perClause.length() - 1));
} else {
throw new IllegalStateException("Per-clause not recognized: " + perClause);
}
} else {
return null;
}
}
public AjType<?>[] getAjTypes() {
Class[] classes = clazz.getClasses();
return toAjTypeArray(classes);
}
public Field getDeclaredField(String name) throws NoSuchFieldException {
Field f = clazz.getDeclaredField(name);
if (f.getName().startsWith(ajcMagic)) throw new NoSuchFieldException(name);
return f;
}
// 这个有点意思:表示标注了@Before、@Around注解的并不算真的方法了,不会给与返回了
public Method[] getMethods() {
Method[] methods = clazz.getMethods();
List<Method> filteredMethods = new ArrayList<Method>();
for (Method method : methods) {
if (isReallyAMethod(method)) filteredMethods.add(method);
}
Method[] ret = new Method[filteredMethods.size()];
filteredMethods.toArray(ret);
return ret;
}
private boolean isReallyAMethod(Method method) {
if (method.getName().startsWith(ajcMagic)) return false;
if (method.getAnnotations().length==0) return true;
if (method.isAnnotationPresent(org.aspectj.lang.annotation.Pointcut.class)) return false;
if (method.isAnnotationPresent(Before.class)) return false;
if (method.isAnnotationPresent(After.class)) return false;
if (method.isAnnotationPresent(AfterReturning.class)) return false;
if (method.isAnnotationPresent(AfterThrowing.class)) return false;
if (method.isAnnotationPresent(Around.class)) return false;
return true;
}
// 拿到所有的Pointcut方法 并且保存缓存起来
public Pointcut[] getDeclaredPointcuts() {
if (declaredPointcuts != null) return declaredPointcuts;
List<Pointcut> pointcuts = new ArrayList<Pointcut>();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
Pointcut pc = asPointcut(method);
if (pc != null) pointcuts.add(pc);
}
Pointcut[] ret = new Pointcut[pointcuts.size()];
pointcuts.toArray(ret);
declaredPointcuts = ret;
return ret;
}
// 标注有org.aspectj.lang.annotation.Pointcut这个注解的方法。 相当于解析这个注解吧,最终包装成一个PointcutImpl
// 主义:Spring-aop也有个接口Pointcut,这里也有一个Pointcut接口 注意别弄混了
private Pointcut asPointcut(Method method) {
org.aspectj.lang.annotation.Pointcut pcAnn = method.getAnnotation(org.aspectj.lang.annotation.Pointcut.class);
if (pcAnn != null) {
String name = method.getName();
if (name.startsWith(ajcMagic)) {
// extract real name
int nameStart = name.indexOf("$$");
name = name.substring(nameStart +2,name.length());
int nextDollar = name.indexOf("$");
if (nextDollar != -1) name = name.substring(0,nextDollar);
}
return new PointcutImpl(name,pcAnn.value(),method,AjTypeSystem.getAjType(method.getDeclaringClass()),pcAnn.argNames());
} else {
return null;
}
}
// 最终返回的对象为AdviceImpl实现类
public Advice[] getDeclaredAdvice(AdviceKind... ofType) { ... }
public Advice[] getAdvice(AdviceKind... ofType) { ... }
private void initDeclaredAdvice() {
Method[] methods = clazz.getDeclaredMethods();
List<Advice> adviceList = new ArrayList<Advice>();
for (Method method : methods) {
Advice advice = asAdvice(method);
if (advice != null) adviceList.add(advice);
}
declaredAdvice = new Advice[adviceList.size()];
adviceList.toArray(declaredAdvice);
}
// 标注了各个注解的 做对应的处理
private Advice asAdvice(Method method) {
if (method.getAnnotations().length == 0) return null;
Before beforeAnn = method.getAnnotation(Before.class);
if (beforeAnn != null) return new AdviceImpl(method,beforeAnn.value(),AdviceKind.BEFORE);
After afterAnn = method.getAnnotation(After.class);
if (afterAnn != null) return new AdviceImpl(method,afterAnn.value(),AdviceKind.AFTER);
AfterReturning afterReturningAnn = method.getAnnotation(AfterReturning.class);
if (afterReturningAnn != null) {
// 如果没有自己指定注解pointcut()的值,那就取值为value的值吧~~~
String pcExpr = afterReturningAnn.pointcut();
if (pcExpr.equals("")) pcExpr = afterReturningAnn.value();
// 会把方法的返回值放进去、下同。。。 这就是@After和@AfterReturning的区别的原理
// 它可议自定义自己的切点表达式咯
return new AdviceImpl(method,pcExpr,AdviceKind.AFTER_RETURNING,afterReturningAnn.returning());
}
AfterThrowing afterThrowingAnn = method.getAnnotation(AfterThrowing.class);
if (afterThrowingAnn != null) {
String pcExpr = afterThrowingAnn.pointcut();
if (pcExpr == null) pcExpr = afterThrowingAnn.value();
return new AdviceImpl(method,pcExpr,AdviceKind.AFTER_THROWING,afterThrowingAnn.throwing());
}
Around aroundAnn = method.getAnnotation(Around.class);
if (aroundAnn != null) return new AdviceImpl(method,aroundAnn.value(),AdviceKind.AROUND);
return null;
}
// 必须不是切面才行哦~~~~
public boolean isLocalClass() {
return clazz.isLocalClass() && !isAspect();
}
public boolean isMemberClass() {
return clazz.isMemberClass() && !isAspect();
}
// 内部类也是能作为切面哒 哈哈
public boolean isMemberAspect() {
return clazz.isMemberClass() && isAspect();
}
public String toString() { return getName(); }
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://cjdhy.blog.csdn.net/article/details/124333897
内容来源于网络,如有侵权,请联系作者删除!