Spring-AOP

前言

在面象对象的语言中,一段逻辑的使用都是由对象之间的相互调用来完成的。将对象抽象为点,调用关系抽象为点与点之间的连接,就是一张图形结构。但之所以引入面向对象的语言,是由于软件开发的规模不断增加所产生的。规模太大,对象调用这张大图就会很复杂,无法便于分析与维护。
我们往往需要将对象关系进行分类。对应到我们的对象之间的调用关系这张大图上就是说,我们可以站在某一种思想角度将一组有相同调用关系的对象进行归类专门做处理,感觉就像是对这一类对象从其它对象的调用关系中切出来处理,面向切面编程因些而得名。

使用

下面以注解的方式为例来说明如何使用spring的AOP。

首先,需要引入spring-aop的组件包

        
            org.springframework
            spring-aspects
            xxx
        

从以下图中,可以看到根据包的依赖关系,会包含aspectjweaver包,可能根据Spring所使用的版本,会有不同组件的依赖:


aop-dependencies.png

创建一个类,并使用@Aspect注解,创建一个切面类。

@Aspect
public class LogAspects {

在切面类中,使用@Pointcut注解,创建一个切面,申明我们要对哪些接口或类的方法产生影响:

    @Pointcut("execution(public int com.going.spring.aop.InterfaceOrClass.*(..))")
    public void pointcut(){};

再在切面类中,使用@Before@After@AfterReturning@AfterThrowing@Around具体定义对切面影响的内容。

    @Before("pointcut()")
    public void logStart(JoinPoint joinPoint){
        //TODO
    }
    
    @After("pointcut()")
    public void logEnd(JoinPoint joinPoint){
        //TODO
    }
    
    @AfterReturning(value="pointcut()",returning="result")
    public void logReturn(JoinPoint joinPoint,Object result){
        //TODO
    }
    
    @AfterThrowing(value="pointcut()",throwing="exception")
    public void logException(JoinPoint joinPoint,Exception exception){
        //TODO
    }

最后,通过配置文件或者配置类打开Spring-AOP的功能即可。

@EnableAspectJAutoProxy
@Configuration
public class AopConfiguration {

源码分析Spring AOP实现方式

配置类上添加注解@EnableAspectJAutoProxy开启AOP功能;
注解@EnableAspectJAutoProxy导入一个AspectJAutoProxyRegistrar类;
AspectJAutoProxyRegistrar类会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator是一个后置处理器,该处理器的postProcessBeforeInstantiation()方法根据切面配置信息,为对象创建代理对象;
其中postProcessBeforeInstantiation()方法是 AnnotationAwareAspectJAutoProxyCreator对象对接口InstantiationAwareBeanPostProcessor的实现,该方法将在对象创建之后,在属性赋值之前被调用:

Perform operations after the bean has been instantiated, via a constructor or factory method,but before Spring property population (from explicit properties or autowiring) occurs. 

This is the ideal callback for performing custom field injection on the given beaninstance, right before Spring's autowiring kicks in.

创建代理对象的功能最终将由DefaultAopProxyFactory类的createAopProxy()方法实现。根据以下的代理可以看出,SpringAOP在创建代理对象时,如果目标注对象的切面是有接口自定的,将通过JDK的动态代理来实现,如果是非接口,将通过Cglib来实现。

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

你可能感兴趣的:(Spring-AOP)