1.1动态AOP使用实例
(1) 创建用于拦截的bean
public class TestBean {
private String testStr="testStr";
public String getTestStr() {
return testStr;
}
public void setTestStr(String testStr) {
this.testStr=testStr;
}
public void test(){
System.out.println("test");
}
}
(2) 创建Advisor
@Aspect
public class AspectJTest {
@Pointcut("execution(* *.test(. .) )")
public void test() {
}
@Before("test()")
public void beforeTest(){
System.out.println("beforeTest")
}
@After("test()")
public void afterTest(){
System.out.println("afterTest")
}
@Around("test()")
public Object aroundTest(ProceedingJoinPoint p){
System.out.println("before1");
Object o = null;
try {
o= p.proceed();
} catch (Throwable e){
e.printlnStackTrace();
}
System.out.println("after1");
return 0;
}
}
(3) 创建配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy>
<bean id="test" class="test.TestBean" />
<beanclass="test.AspectJTest " />
</beans>
(4) 测试
@Test
public void testSimpleLoad(){
ApplicationContext bf = new ClassPathXmlApplicationContext("beanFactoryTest.xml");
MyTestBean bean=(MyTestBean) bf.getBean("myTestBean");
bean.test();
}
控制台输出:
beforeTest
before1
test
afterTest
after1
1.2 动态AOP自定义标签
如果声明了自定义的注解, 那么就一定会在程序中的某个地方注册了对应的解析器
public class AopNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
//注册AspectJAutoProxyBeanDefinitionParser
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
逻辑分析:
在解析配置文件的时候, 一旦遇到aspectj-autoproxy 注解时就会使用解析器AspectJAutoProxyBeanDefinitionParser进行解析
1.2.1 注册AnnotationAwareAspectJAutoProxyCreator
所有解析器, 因为是对BeanDefinitionParse接口的统一实现,入口都是从parse方法开始的;
AspectJAutoProxyBeanDefinitionParser的parse方法如下:
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册AspectJAnnotationAutoProxyCreator(具体实现类是AnnotationAwareAspectJAutoProxyCreator)
//AnnotationAwareAspectJAutoProxyCreator的作用:基于 Bean 中的 AspectJ 注解标签的匹配规则创建代理
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//对于注解中子类的处理
extendBeanDefinition(element, parserContext);
return null;
}
//public abstract class AopNamespaceUtils
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//1.注册或升级AutoProxyCreator,
//定义beanName为org.springframework.beans.factory.config.internalAutoProxyCreator的BeanDefinition
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//2.对于proxy-targe-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//3.注册组件并通知,便于监听器进一步处理
//其中beanDefinition的className为AnnotationAwareAspectJAutoProxyCreator
registerComponentIfNecessary(beanDefinition, parserContext);
}
(1)注册或升级AnnotationAwareAspectJAutoProxyCreator
对于aop的实现, 基本上都是靠AnnotationAwareAspectJAutoProxyCreator去完成,它可以根据@point注解定义的切点来自动代理相匹配的bean;
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
//将AnnotationAwareAspectJAutoProxyCreator代理创建器的类路径传递过去
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//判断自动代理创建器是否已存在
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
//获取已存在的自动代理创建器
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//如果存在的自动代理创建器与即将创建的不一致,那么需要根据优先级来判断到底需要使用哪种
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
//获取优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
//改变bean最重要的就是改变bean对应的className属性
apcDefinition.setBeanClassName(cls.getName());
}
}
//如果已存在自动代理创建器与将要创建的一致,那么无需再次创建
return null;
}
//如果自动代理创建器不存在,则创建
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//注册
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
逻辑分析:
如果已经存在了自动代理创建器, 而且存在的自动代理创建器与现在的不一致, 那么需要根据优先级来判断到底需要使用哪个
(2) 处理porxy-target-class以及expose-proxy属性
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
//对于proxy-target-class属性的处理
//proxy-target-class:强制使用CGLib为目标对象创建代理(如果没有设置该属性的话,如果目标对象实现了至少一个接口,则会使用JDK的动态代理)。
//但是,CGLib的有两个问题需要考虑:1.无法代理final class,因为CGLib是通过生成子类来创建代理对象的;2.需要无参构造函数
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//对于expose-proxy属性的处理(expose-proxy:为了解决目标对象内部的自我调用时,无法实现切面的增强的问题)
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
逻辑分析:
proxy-target-class: springAOP部分使用JDK动态代理或者CGLIB来为目标对象创建代理; 如果被代理的目标兑现实现了至少一个接口, 则会使用JDK动态代理; 所有该目标类型实现的接口都将被代理; 若该目标对象没有实现任何接口, 则创建一个CGLIB代理; 如果希望强制使用CGLIB代理(例如希望代理目标对象的所有方法, 而不只是实现自接口的方法)可以将proxy-target-class设为true; CGLIB代理需要注意的是:
- 无法通知(advise)Final方法, 因为他们不能被覆盖
- 需要将CGLIB二进制发行包放在classpath下
JDK动态代理: 其代理对象必须是某个接口的实现, 通过在运行期间创建一个接口的实现类来完成对目标对象的代理
CGLIB代理: 实现原理类似于JDK动态代理, 只是它在运行期间生成的代理对象时针对目标类扩展的子类; CGLIB是高效的代码生成包, 底层是依靠ASM操作字节码实现的, 性能比JDK强
expose-proxy: 有时候目标对象内部调用将无法实施切面中的增强 例如:
public interface AService{
public void a();
public void b();
}
@Service()
public class AServiceImpl implement AService{
@Transactional(propagation = Propagation.REQUIRED)
public void a(){
this.b();
}
@Transactional(propagation = Propagation.REQUIRED_NEW)
public void b(){
}
}
分析:
此处的this指向目标对象, 因此调用this.b() 将不会执行b事务切面, 即不会执行事务增强, 因此b方法的事务定义"@Transactional(propagation = Propagation.REQUIRED_NEW)“将不会实施, 为解决该问题, 可以设置expose-proxy为true; 并将"this.b()” 修改为"((AService)AopContext.currentProxy()).b()" 即可; 通过该修改便可以完成对a和b方法的通知增强
1.3 创建AOP代理
AnnotationAwareAspectJAutoProxyCreator类实现了BeanPostProcessor接口, 那么在spring加载每个bean时会在调用初始化方法前后调用postProcessBeforeInitialization和postProcessorAfterInitialization方法来执行代理包装逻辑的
AbstractAutoProxyCreator为AnnotationAwareAspectJAutoProxyCreator的父类
//public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
//根据给定的bean的class和name构建出个key,格式:beanClassName_beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//如果条件符合,则为bean生成代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果已经处理过(targetSourcedBeans存放已经增强过的bean)
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//advisedBeans的key为cacheKey,value为boolean类型,表示是否进行过代理
//已经处理过的bean,不需要再次进行处理,节省时间
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//给定的bean类是否已经代表一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要自动代理
//如果一个bean继承自Advice、Pointcut、Advisor、AopInfrastructureBean 或者 带有@Aspect注解,或被Ajc(AspectJ编译器)编译都会被认定为内部基础设置类
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//获取所有适合该bean的增强Advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果获取的增强不为null,则为该bean创建代理(DO_NOT_PROXY=null)
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理
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;
}
逻辑分析:
(1) 获取增强方法或者增强器
(2) 根据获取的增强进行代理
1.3.1 获取适合某个bean的增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(),beanName, null)
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
//获取合适的增强器
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
//数组为空,返回null
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
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;
}
逻辑分析:
(1) 获取所有的增强器
(2) 在获取到的增强器中寻找适用于该bean的增强并应用
1.3.1.1 获取所有的增强器
//public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
/**
* 增强器分类两类处理:一种是通过<aop>标签添加的增强,这部分会在解析配置文件的时候添加到Spring容器中,
* 只需要获取当前容器中Advisor类型的bean就可以获取到该类增强;另一中是通过注解添加的增强,获取此类增强还需要对bean进行遍历解析
*/
//在这里调用父类方法加载配置文件中的AOP声明
List<Advisor> advisors = super.findCandidateAdvisors();
//获取Bean的注解增强的功能
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
逻辑分析:
当前分析的是使用注解进行的AOP, 所以对于findCandidateAdvisors的实现其实是由AnnotationAwareAspectJAutoProxyCreator 类完成的 该类间接继承了AbstractAdvisorAutoProxyCreator类,在实现获取增强的方法中除了保留父类的获取配置文件中定义的增强外, 同时添加了获取bean的注解增强的功能, 那么其真正的实现是由
this.aspectJAdvisorsBuilder.buildAspectJAdvisors()来实现的
在findCandidateAdvisors方法中分为两部分处理:
(1)调用父类的findCandidateAdvisors方法获取配置文件中定义的增强
(2)通过this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法来获取Bean的注解增强的功能
1.获取配置文件中定义的增强
List<Advisor> advisors = super.findCandidateAdvisors()
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
//获取所有增强器的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
//遍历所有增强器的名称,将其实例化
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
2.获取Bean的注解增强
public List<Advisor> buildAspectJAdvisors() {
//因为解析会很消耗性能,所以Spring会使用aspectBeanNames保存解析结果
List<String> aspectNames = null;
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
//获取所有的beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
//遍历所有的beanName,找出对应的增强方法
for (String beanName : beanNames) {
//不合法的bean则略过,由子类定义规则,默认返回true
if (!isEligibleBean(beanName)) {
continue;
}
//获取对应的bean类型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//如果存在@Aspect注解的类
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
//保存bean类型以及@Aspect注解信息
AspectMetadata amd = new AspectMetadata(beanType, beanName);
//检查@Aspect注解的value值,验证生成的增强是否是单例
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析标记AspectJ注解中的增强方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
//如果bean是单例,则缓存bean的增强器
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
//bean非单例,只能缓存bean对应的增强器创建工厂
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
//切面创建模式非单例
else {
//如果切面是非单例,但是bean是单例,抛出异常
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
//获取所有切面
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
/**
* 如果不是第一次解析切面,证明增强器已经被缓存过了,会执行下面的代码,查询缓存
*/
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
//记录在缓存中
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
逻辑分析:
(1) 获取所有的beanName,这一步骤中所有在beanFactory中注册的Bean都会被提取出来
(2) 遍历所有beanName, 并找出声明AspectJ注解的类, 进行进一步的处理
(3) 对标记为AspectJ注解的类进行增强器的提取
(4) 将提取的结果记录在缓存中并返回
2.1 对标记为AspectJ注解的类进行增强器的提取:
MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory)
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
//获取标记为AspectJ的类
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
//获取标记为AspectJ的name
final String aspectName = maaif.getAspectMetadata().getAspectName();
//验证
validate(aspectClass);
//我们需要使用装饰器包装MetadataAwareAspectInstanceFactory
//这样它只会实例化一次
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(maaif);
final List<Advisor> advisors = new LinkedList<Advisor>();
//getAdvisorMethods方法会遍历该类中所有方法,筛选出不带有@Pointcut注解的方法(@Pointcut标记切点的方法)
for (Method method : getAdvisorMethods(aspectClass)) {
//创建增强器对象
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
//如果寻找的增强器不为空,而且有配置了增强延迟初始化那么需要在首位加入同步实例化增强器,
//通过在头部加入SyntheticInstantiationAdvisor增强器,达到延迟初始化切面bean的目的
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
//获取DeclareParents注解
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
逻辑分析:
(1) 遍历标记为AspectJ的类中的所有方法获取增强器(筛选出不带有@Pointcut注解的方法)
(2) 增加同步实例化增强器
(3) 获取DeclareParents
2.1.1普通增强器的获取
普通增强器的获取逻辑通过getAdvisor方法实现, 实现步骤包括对切点的注解的获取以及根据注解信息生成增强器
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName)
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
int declarationOrderInAspect, String aspectName) {
//验证目标bean的Class对象
validate(aif.getAspectMetadata().getAspectClass());
//获取方法上的注解信息,并将配置的表达式封装为AspectJExpressionPointcut
AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
if (ajexp == null) {
return null;
}
//将Pointcut对象以及Method对象封装到InstantiationModelAwarePointcutAdvisorImpl类中,组合成为一个增强器
return new InstantiationModelAwarePointcutAdvisorImpl(
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
}
(1) 切点信息的获取; 所谓获取切点信息就是指定注解的表达式信息的获取
如:"@Before(“test()”)"
AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//获取指定方法上的注解,并使用AspectJAnnotation封装
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//使用AspectJExpressionPointcut实例封装获取的信息
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
//设置切入点信息
//@Pointcut("execution(* *.*test(..))")中的execution(* *.*test(..))信息
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
return ajexp;
}
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
//将所有的注解类型封装成一个数组
Class<?>[] classesToLookFor = new Class<?>[] { Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
//遍历所有的注解类型,将注解的方法与注解类型封装到AspectJAnnotation类中
for (Class<?> c : classesToLookFor) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
//获取指定方法上的注解并使用AspectJAnnotation封装
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<A>(result);
}
else {
return null;
}
}
(2) 根据切点信息生成增强; 所有的增强都由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl统一封装的
return new InstantiationModelAwarePointcutAdvisorImpl(
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName)
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
this.declaredPointcut = ajexp;
this.method = method;
this.atAspectJAdvisorFactory = af;
this.aspectInstanceFactory = aif;
this.declarationOrder = declarationOrderInAspect;
this.aspectName = aspectName;
if (aif.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(aif.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, aif);
this.lazy = true;
}
else {
// A singleton aspect.
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
this.pointcut = declaredPointcut;
this.lazy = false;
}
}
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.atAspectJAdvisorFactory.getAdvice( this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
//声明注解的所在类
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
//获取方法上的注解(上面已经获取过了一次,这里重复获取了)
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//检查声明类上是否有@Aspect注解
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
//根据不同的注解类型封装不同的增强器
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrderInAspect);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
逻辑分析:
spring会根据不同的注解生成不同的增强器, 例如AtBefore会对应生成AspectJMethodBeforeAdvice,而在AspectJMethodBeforeAdvice中完成了增强的逻辑
2.1.2增加同步实例化增强器
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory)
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
//目标方法调用
@Override
public void before(Method method, Object[] args, Object target) {
//简单初始化aspect
aif.getAspectInstance();
}
});
}
}
逻辑分析:
如果寻找的增强器不为空,而且有配置了增强延迟初始化, 那么就需要在首位加入同步实例化增强器
2.1.1获取DeclareParents注解
Advisor advisor = getDeclareParentsAdvisor(field)
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
// Not an introduction field
return null;
}
if (DeclareParents.class == declareParents.defaultImpl()) {
// This is what comes back if it wasn't set. This seems bizarre...
// TODO this restriction possibly should be relaxed
throw new IllegalStateException("defaultImpl must be set on DeclareParents");
}
return new DeclareParentsAdvisor(
introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
逻辑分析:
DeclareParents主要用于引介增强的注解形式的实现, 而其实现方式与普通的增强很相似,只不过使用DeclareParentsAdvisor对功能进行封装
1.3.1.2 寻找匹配的增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
//通过一个ThreadLocal变量,设置当前代理的beanName
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//过滤已经得到的advisors
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
//存储过滤出来的增强器
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
//首先处理引介增强
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
//引介增强已经处理
if (candidate instanceof IntroductionAdvisor) {
continue;
}
//对于普通bean的处理
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
findAdvisorsThatCanApply方法的主要功能是寻找所有增强中适用于当前class的增强器; 引介增强与普通的增强是处理不一样的,所以分开处理; 而对于真正的匹配是在canApply方法中实现的
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
//引介增强是通过设置ClassFilter进行匹配
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) {
Assert.notNull(pc, "Pointcut must not be null");
//1.ClassFilter匹配
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//MethodMatcher的匹配
//如果切点的MethodMatcher类型为MethodMatcher.TRUE,则表示对所有方法都进行匹配
MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//遍历目标类所有接口中所有定义的方法,通过MethodMatcher进行匹配
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
//匹配增强器适用的方法
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}