【有书共读】《Spring源码深度解读》第七章AOP
第7章 AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态***实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
7.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");
}
@Around("test()")
public Object aroundTest(ProceedingJoinPoint p){
System.out.println("before1");
Object o = null;
try{
o = p.proceed();
}catch(Throwable e){
e.printStackTrace();
}
System.out.println("after1");
return o;
}
}
3) 创建配置文件。
<aop:aspectj-autoproxy/>
<bean id="test" class="test.TestBean"/>
<bean class="test.AspectJTest"/>
4) 测试。
public static void main(String[] args) {
ApplicationContext bf = new ClassPathXmlApplicationContext("aspectTest.xml");
TestBean bean = (TestBean)bf.getBean("test");
bean.test();
}
5) 结果
不出意外打印出
beforeTest
before1
test
after1
7.2 动态AOP自定义标签
自定义注解,如果声明了自定义的注解,那么就一定会在程序中的某个地方注册了对应的解析器,我们可以在AopNamespaceHandler中函数
public void init()
{
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
7.2.1 注册AnnotationAwareAspectJ AutoProxyCreator
所有解析器,因为是对BeanDefinitionParser接口的统一实现,入口都是从parse函数开始的,AspectJAutoProxyBeanDefinitionParser的parse函数如下:
public BeanDefinition parse(Element element, ParserContext parserContext)
{
//注册AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//对注解中子类的处理
extendBeanDefinition(element, parserContext);
return null;
}
其中registerAspectJAnnotationAutoProxyCreatorIfNecessary函数是我们比较关心的,也是关键逻辑的实现
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement)
{
//注册或升级AutoProxyCreator定义beanName为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的className为AnnotationAwareAspectJAutoProxyCreator
registerComponentIfNecessary(beanDefinition, parserContext);
}
7.3 创建AOP***
AOP的主要逻辑代码如下:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object ***Key = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(***Key)) {
return wrapIfNecessary(bean, beanName, ***Key);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object ***Key) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(***Key))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(***Key, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(***Key, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(***Key, proxy.getClass());
return proxy;
}
this.advisedBeans.put(***Key, Boolean.FALSE);
return bean;
}
创建***主要进行了两个步骤
1) 获取增强方法或者增强器
2) 根据获取的增强进行***
增强的实现:
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
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;
}
7.3.1 获取增强器
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be ***d by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
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 ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> ***dAdvisors = this.advisorsCache.get(aspectName);
if (***dAdvisors != null) {
advisors.addAll(***dAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
至此实现对Advisor的获取
7.3.2 寻找匹配的增强器
选择满足我们配置的通配符的增强器,主要实现在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);
}
}
7.3.3 创建***
在获取所有对应bean的增强器后,便可以进行***的创建了
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
7.4 静态AOP使用示例
首先需要对Spring的全局配置文件修改,加入LWT开关,LWT指加载时织入,在虚拟机载入字节码文件时动态织入AspectJ切面。其次加入aop.xml,在class目录下的meta-inf下建立aop.xml,告诉AspectJ需要哪个包进行织入,并使用哪些增强器。同时加入启动参数。
7.5 创建AOP静态***
AOP的静态***主要是在虚拟机启动时通过改变目标对象字节码的方式来完成对目标对象的增强,它与动态***相比具有更高的效率,因为在动态***调用的过程中,还需要一个动态创建***类并***目标对象的步骤,而静态***则是在启动时便完成了字节码增强,当系统再次调用目标类时与调用正常的类并无差别,所以在效率上会相对高些