spring aop简称面向切面编程,不同于OOP即面向对象编程,OOP作为开发业务时,如需要引入安全检测、系统日志、监控等功能时,每个对象都需要引入公共代码,会造成不可维护和冗余代码,AOP的横空出世,正是为了解决OOP纵向的继承关系,AOP关心的是横向切面关系,在某一时刻进行切入,执行一些额外的逻辑。
本文不对较低的sprig aop版本进行分析,直接从spring支持@AspectJ开始进行分析,该注解中主要是在切面中定义一个切点和切入点即可。
使用Aop两种方式,一种是注解方式,另一种是XML配置文件,本次采用最基础的XMl方式去创建AOP;
public class TestAop {
@Pointcut("execution(* com.spring.service.PlayerService.player(int))&&args(number)")
public void pointCut(int number){}
@Before(value = "pointCut(number)")
public void before(int number){
System.out.println("TestAop is before! " + number);
}
@After(value = "pointCut(number)")
public void after(int number){
System.out.println("TestAop is after! " + number);
}
@AfterReturning(value = "pointCut(number)")
public void afterReturning(int number){
System.out.println("TestAop is afterReturning! " + number);
}
@AfterThrowing(value = "pointCut(number)")
public void afterThrowing(int number){
System.out.println("TestAop is afterThrowing! " + number);
}
@Around(value = "pointCut(number)")
public void around(ProceedingJoinPoint joinPoint,int number) throws Throwable {
joinPoint.proceed();
System.out.println("TestAop is around! "+number);
}
}
public interface PlayerService {
void player(int number);
}
public class PlayerServiceImpl implements PlayerService {
@Override
public void player(int number) {
System.out.println("Player WuBai: "+number);
}
}
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd" default-autowire="byName">
<aop:aspectj-autoproxy />
<bean id = "playerService" class="com.spring.service.PlayerServiceImpl"></bean>
<bean class="com.spring.aop.TestAop"/>
</beans>
public class Test1 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/applicationContext.xml");
PlayerService players = applicationContext.getBean("playerService", PlayerService.class);
players.player(3);
}
}
输出如下:
TestAop is before! 3
Player WuBai: 3
TestAop is around! 3
TestAop is after! 3
TestAop is afterReturning! 3
Spring Aop发挥作用,前提是要开启对aop的支持,开启方式用两种,XMl配置文件开启方式:
注解开启方式:在基于注解的容器配置类添加@EnableAspectJAutoProxy即可,上述两种方式均可开启Spring对Aop的支持,
本文分析
Spring 在容器启动时,首先会去解析配置文件或者配置注解,解析配置文件为BeanDefinition时伴随着解析
obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinitions(beanFactory)->loadBeanDefinitions(beanDefinitionReader) -> reader.loadBeanDefinitions(configResources)->loadBeanDefinitions(resource)->loadBeanDefinitions(new EncodedResource(resource)) ->doLoadBeanDefinitions(inputSource, encodedResource.getResource())->registerBeanDefinitions(doc, resource) ->documentReader.registerBeanDefinitions(doc, createReaderContext(resource))->doRegisterBeanDefinitions(doc.getDocumentElement()) ->(解析核心方法)parseBeanDefinitions(root, this.delegate)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
上述解析spring默认标签或者用户自定义标签时会调用下面parseCustomElement方法,里面就是aop开始发挥作用的地方,
NamespaceHandlerResolver中定义的resolve方法,返回的类型为NamespaceHandler,实际上是通过AopNamespaceHandler子类去实例化完成;
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
DefaultNamespaceHandlerResolver中定义了resolve,其中核心点为namespaceHandler.init()方法,此步是spring支持Aop的关键
public NamespaceHandler resolve(String namespaceUri) {
Map<String, Object> handlerMappings = getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
namespaceHandler.init();//支持aop的前提条件
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
"] for namespace [" + namespaceUri + "]", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
className + "] for namespace [" + namespaceUri + "]", err);
}
}
}
在第一步中提到了Aop在何时开始进行调用AOP环境,init()中可直观的看到对aspectj-autoproxy的注册,使用AspectJAutoProxyBeanDefinitionParser作为AOP的默认解析器,代码如下:
public void init() {
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
在Spring中所有的BeanDefinition解析器基本都是从parse出发,AOP解析器也一样,里面主要是registerAspectJAnnotationAutoProxyCreatorIfNecessary方法发挥作用:
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//处理被继承的子类
extendBeanDefinition(element, parserContext);
return null;
}
注册AnnotationAwareAspectJAutoProxyCreator的关键核心点:
(1)处理org.springframework.aop.config.internalAutoProxyCreator类型的BeanDefinition;
(2)处理proxy-target-class和expose-proxy;
(3)将(1)生成的beanDefinition注册到容器监听器中。
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//处理org.springframework.aop.config.internalAutoProxyCreator类型的BeanDefinition
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//处理proxy-target-class和expose-proxy
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//将该方法中第一步生成的beanDefinition注册到容器的监听器中
registerComponentIfNecessary(beanDefinition, parserContext);
}
主要是由AnnotationAwareAspectJAutoProxyCreator类来支持,根据@PointCut定义切点,切点中定义了匹配bean的语法,用于创建代理对象,由AnnotationAwareAspectJAutoProxyCreator来实现该功能:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
主要判断是否采用了用户在XML中配置的org.springframework.aop.config.internalAutoProxyCreator类型的bean代理器,如果存在则需要进行优先级的判定并根虎优先级采用那个类型作为BeanDefinition的class类型
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable 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) {
apcDefinition.setBeanClassName(cls.getName());//改变BeanDefinition中的class类型
}
}
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;
}
XML配置文件中是否存在PROXY_TARGET_CLASS_ATTRIBUTE和EXPOSE_PROXY_ATTRIBUTE的配置,存在则进行自动代理
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
强制使用了AUTO_PROXY_CREATOR_BEAN_NAME类型即org.springframework.aop.config.internalAutoProxyCreator类来
处理proxy-target-class和expose-proxy两个属性
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);
}
}
public 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属性决定了采用基于接口的JDK动态代理,还是基于字节码文件的cglib代理,两者的区别为前者是对被代理的目标对象是否有实现接口,如果实现了接口,那么对于这种对象是使用JDK动态代理来生成,如果目标对象没有实现任何接口,则默认采用cglib代理生成目标对象。
强制使用cglib只需要在配置文件中配置proxy-target-class="true"即可,缺陷是无法通知final修饰符所修饰的方法,cglib包需要放在classpath下。
代理模式类型:
JDK动态代理:被代理的目标对象必须是某个接口的实现类,在运行期间创建接口的实现类来完成对目标对象的代理;
cglib代理:在运行期间生成目标对象的代理对象,针对目标扩展类的子类,cglib底层依赖ASM即字节码编辑类库,操作字节码实现,性能比JDK代理强。
expose-proxy属性:主要是解决目标对象自身内部调用导致无法增强的问题如类中一个方法a调用自身类中的方法b,两个方法都加了事务,自身this.b()会导致其失效,配置该属性为true时,再将this.b()换为((T)AopContext.currentProxy).b()即可。
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
parserContext.registerComponent(
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
}
}
AnnotationAwareAspectJAutoProxyCreator类层次结构如下:
AnnotationAwareAspectJAutoProxyCreator是在AOP初始化环境中被注册进去,即在Spring加载过程中,注册时会执行其间接父类AbstractAutoProxyCreator中的postProcessAfterInitialization方法,因AnnotationAwareAspectJAutoProxyCreator中间接继承的类中实现了BeanPostProcessor后置处理器,在Spring加载时会执行后置处理器,该执行逻辑,自行查看Spring源码分析一——容器篇中有详细介绍。
AbstractAutoProxyCreator–>postProcessAfterInitialization方法如下:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//基于className或beanName创建一个key,可能是&+beanName,也可能是className
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//earlyProxyReferences是一个并发map,主要是存储需要被代理bean
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//核心方法wrapIfNecessary,对bean进行封装并代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;//该处表明bean为null或已经被代理过
}
根据beanClass和beanName来确定key的生成,同时判断是否为BeanFactory类型,此类型则返回key为&+beanName。
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
if (StringUtils.hasLength(beanName)) {
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
}else{
return beanClass;
}
}
spring是否真正创建代理需要进行一系列判断,是否被处理过,是否不需要被代理等,最终获取增强方法和创建代理,否则使用一些辅助类变量进行缓存如targetSourcedBeans、advisedBeans、proxyTypes作为是否代理bean的辅助缓存。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//是否已经被spring处理过,targetSourcedBeans集合Set存储
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//利用advisedBeans并发map集合存储,直接过滤不需要处理的bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//基础设施类不被代理和特殊配置bean不被代理的进行记录,使用advisedBeans并发集合存储
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//存在增强的方法进行代理,主要是获取增强方法和创建代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, 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;
}
//执行到此处代表上述逻辑都不符合,则表明该bean不需要被代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
wrapIfNecessary方法中如果该bean符合被代理的条件,则会进行两个核心步骤,分别为获取增强方法和创建代理。
wrapIfNecessary中的getAdvicesAndAdvisorsForBean方法是委托给子类AbstractAdvisorAutoProxyCreator去进行实现,主要就是获取Advisor增强方法,代码如下:
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//获取所有的Advisor增强方法
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
findEligibleAdvisors主要是做了两个事情:
1)找寻所有的增强器;
2)寻找匹配的代理增强器。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();//寻找所有增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//应用增强器到增强方法
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);//进行排序
}
return eligibleAdvisors;
}
获取增强器,是由AnnotationAwareAspectJAutoProxyCreator类实现,先调用父类AbstractAdvisorAutoProxyCreator中的findCandidateAdvisors方法获取配置文件XML中的aop声明,自身的注解aop声明交由buildAspectJAdvisors方法去实现,如下:
protected List<Advisor> findCandidateAdvisors() {
//调用父类在配置文件中的aop声明
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
//获取自身注解定义的aop声明,并合并到配置文件中声明的AOP中
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
buildAspectJAdvisors方法是AOP注解中的核心方法,其主要思想分为以下步骤:
1)获取spring容器中的所有bean;
2)遍历bean,找到被AspectJ注解的类;
3)对标记了AspectJ注解的类进行增强器提取;
4)将提取结果缓存到变量中,便于使用。
代码如下:
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;//获取被AspectJ注解类的beanName
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;//加锁重新获取,保证加锁过程中是最新的数据
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//从容器中获取所有的beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {//默认返回的true,自定义扩展可更改
continue;
}
//获取bean的class类型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//提取被AspectJ注解过的类
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);//将其添加到aspectNames中,遍历完时重新赋值给aspectBeanNames
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析被AspectJ注解的增强方法,getAdvisors方法是提取的核心方法,详细请查看[Spring源码番外篇-AOP补充一](http://t.csdn.cn/0wxaC)
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);//单例缓存存储
}else {
this.aspectFactoryCache.put(beanName, factory);//原型作用域的bean存储
}
advisors.addAll(classAdvisors);
}else {
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);//bean作用域为原型的存储
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
//将增强方法缓存
List<Advisor> advisors = new ArrayList<>();
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)中获取到的所有增强器与Point中的表达式进行结合,满足于我们在spring中定义的具体业务方法进行应用。具体表现在findAdvisorsThatCanApply方法中,代码如下:
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//在获取到的所有增强器中来过滤不是该表达式匹配的增强方法
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
findAdvisorsThatCanApply方法主要用于过滤不是对应bean业务的表达式增强器,canApply方法是真正过滤的关键点,分两步处理,第一步是先处理IntroductionAdvisor这种类型的增强器,第二步是处理普通类型的增强器,canApply方法因本文篇幅受限,请查看spring源码分析番外篇——AOP补充一
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {//开始遍历过滤
//第一步先处理IntroductionAdvisor增强器即支持用户自定义实现IntroductionAdvisor,进行个性化开发
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//第二步处理普通的增强器
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
创建代理的核心逻辑:
1)获取代理配置类的属性,伴随一些属性设置;
2)是否创建代理接口;
3)封装advisor并添加到ProxyFactory;
4)设置被代理的类;
5)开放性设计定制代理类ProxyFactory,由子类去个性化实现改变;
6)获取代理。
在第(1)中获取增强方法后,紧接着需要创建代理,也是AOP实现的另一个关键点,代码如下:
createProxy中核心点是两步:
1)封装advisor;
2)生成代理。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//判断ConfigurableListableBeanFactory容器中是否存在beanName,存在则设置属性originalTargetClass
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//初始化ProxyFactory对象
ProxyFactory proxyFactory = new ProxyFactory();
//将当前对象中可能发生变化的属性设置到proxyFactory的属性中
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {//默认是false即取反后为true
//判断preserveTargetClass属性是否保留目标类代理即true代表代理目标类 false代表接口类代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);//直接代理目标类
}else{
//代表preserveTargetClass属性是false,需要使用接口代理目标类
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//封装advisor篇幅较长,使用番外篇AOP阐述,该方法也是比较核心
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);//加入增强器
proxyFactory.setTargetSource(targetSource);//代理的目标类
customizeProxyFactory(proxyFactory);//定制代理
proxyFactory.setFrozen(this.freezeProxy);//代理配置完成后,不允许修改,默认为false
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());//生成代理并返回
}
evaluateProxyInterfaces方法在createProxy方法中被使用接口代理目标类,调用父类ProxyProcessorSupport类中继承的方法,代码如下:
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
//获取目标对象的所有接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;//满足接口代理的条件,改变标记
break;
}
}
if (hasReasonableProxyInterface) {
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);//添加代理接口
}
}else {
proxyFactory.setProxyTargetClass(true);//代表不满足接口代理的条件时,代理目标类
}
}
请查看spring源码番外篇AOP中buildAdvisors方法;
1)创建代理对象
proxyFactory.getProxy(getProxyClassLoader());这行代码是createProxy方法中最后一行,也是生成代理的核心和最后一步,会根据bean的特点和配置共同决定采用常说的那两种代理进行创建即JdkDynamicAopProxy和ObjenesisCglibAopProxy,代码如下:
ProxyFactory类的对象调用getProxy方法,
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);//调用父类ProxyCreatorSupport中的createAopProxy方法创建代理对象
}
ProxyFactory类将创建代理对象的具体直接使用父类ProxyCreatorSupport继承来的同步方法createAopProxy并确保处于创建代理的激活状态,但是父类ProxyCreatorSupport利用自身的成员变量aopProxyFactory去委托给DefaultAopProxyFactory去实现创建代理对象,代码如下:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {//确保处于创建代理中
activate();
}
return getAopProxyFactory().createAopProxy(this);//利用成员变量委托给DefaultAopProxyFactory去实现
}
DefaultAopProxyFactory类实现创建代理,其中Spring中老生常谈的JDK和cglib代理就是这里实现,createAopProxy代码如下:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//bean的aop代理创建配置选择
/**
* optimize:控制cglib代理是否采用优化策略,不建议用户修改该值
* proxyTargetClass:目标类代理是否为本身,为true则代表选择使用cglib模式
* hasNoUserSuppliedProxyInterfaces:是否存在代理接口
*/
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.");
}
//判断该目标代理类是否存在接口或配置文件中配置了使用JDK动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//否则采用cglib去创建代理
return new ObjenesisCglibAopProxy(config);
}else {//不符合JDK代理时,选择cglib代理
return new JdkDynamicAopProxy(config);
}
}
2)获取代理对象
JdkDynamicAopProxy代理模式下获取代理对象,JDK代理核心点是三个函数,分别是构造函数获取目标对象、invoke增强逻辑、getProxy获取代理对象,关于Spring中JdkDynamicAopProxy也是实现了InvocationHandler,并重写了invoke(该方法的重写介绍,请查看Spring源码番外篇AOP补充一),同时也实现了getProxy方法获取代理对象,代码如下:
@Override
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);//创建代理对象
}
CglibAopProxy代理模式下获取代理对象,主要是对目标对象进行判断和验证、Enhancer增强对象、设置拦截器链(核心点)和创建代理类并创建代理实例,getProxy代码如下:
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
//对目标对象进行获取并判断其类型是否包含CGLIB_CLASS_SEPARATOR
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
//验证class
validateClassIfNecessary(proxySuperClass, classLoader);
//使用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 ClassLoaderAwareGeneratorStrategy(classLoader));
//设置拦截器链(核心点)
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
//设置回调器
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
//生成代理类并创建代理实例
return createProxyClassAndInstance(enhancer, callbacks);
}catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",ex);
}catch (Throwable ex) {
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
getCallbacks设置拦截器链,Spring cglib支持很多拦截器,其中常用的是DynamicUnadvisedExposedInterceptor拦截器,将advised属性封装在DynamicAdvisedInterceptor中,然后将封装的对象添加到Callback里面,cglib代理通过DynamicAdvisedInterceptor中的intercept方法来执行,getCallbacks代码如下:
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
//将拦截器封装在DynamicAdvisedInterceptor中
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
Callback targetInterceptor;
//对expose-proxy进行处理并判定是静态StaticUnadvisedExposedInterceptor还是动态处理DynamicUnadvisedExposedInterceptor
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}else{
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
//将拦截器加入到Callback中
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}else {
callbacks = mainCallbacks;
}
return callbacks;
}
DynamicAdvisedInterceptor类实现了MethodInterceptor,则在执行代理对象时会先执行intercept方法,代码如下:
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
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 {
//开始执行拦截链
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}