Spring AOP理解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring AOP理解相关的知识,希望对你有一定的参考价值。

    Spring的核心思想的IOC和AOP。最近学习AOP,对切面的学习有了进一步的认识。

    Spring用代理类包裹切面,把他们织入到Spring管理的bean中。也就是说代理类伪装成目标类,它会截取对目标类中方法的调用,让调用者对目标类的调用都先变成调用伪装类,伪装类中就先执行了切面,再把调用转发给真正的目标bean。这样可以实现对业务代码的最小化侵入。使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性。Spring中日志记录,性能统计,安全控制,事务处理等都是通过AOP来管理的。

技术分享

 

伪装类的实现有两种方式:1.实现和目标类相同的接口。这种兄弟模式下,spring会使用JDK的java.lang.reflect.Proxy类,它允许Spring动态生成一个新类来实现必要的接口,织入通知,并且把对这些接口的任何调用都转发到目标类。

                                   2.生成子类调用,用子类来做为伪装类。这种父子模式下,spring使用CGLIB库生成目标类的一个子类,在创建这个子类的时候,spring织入通知,并且把对这个子类的调用委托到目标类。

相比之下,还是兄弟模式好些,能更好的实现松耦合,尤其在今天都高喊着面向接口编程的情况下,父子模式只是在没有实现接口的时候,也能织入通知,应当做一种例外。

 下面看一个AOP的小应用。目的是为了在addStudent方法执行前后通过AOP来进行相关操作。

在上下文中配置aspectJ。

<aop:aspectj-autoproxy/>
//定义切面,切点。也可以通过注解来实现切面的和切点标识。
<aop:config>
        <aop:aspect id="StudentServiceAspect" ref="studentServiceAspect">
            <aop:pointcut id="businessService" expression="execution(* com.lufax.test.commen.studentService.*.*(..))"/>
            <aop:before method="doBefore" pointcut-ref="businessService"/>
            <aop:after method="doAfter" pointcut-ref="businessService"/>
            <aop:around method="doAround" pointcut-ref="businessService"/>
        </aop:aspect>
    </aop:config>

下面定义studentService的接口。

public interface StudentService {
    public void addStudent(String name);
}

studentService的实现类如下。

public class StudentServiceImp implements StudentService {

    public void addStudent(String name){
        System.out.println("----正在添加" + name+"----");
    }
}

以上接口和实现都是正常的业务逻辑。下面写切面。

public class StudentServiceAspect {
    //在业务代码执行前运行
    public void doBefore(){
        System.out.println("类名:");
        System.out.println("doBefore:开始添加学生");
    }
//业务代码执行后运行
public void doAfter(JoinPoint jp){ System.out.println("doAfter:添加完毕");
//可以通过Joinpoint类来实现日志的打印。记录切点下类和方法名、参数,以便后续快速定位问题所在。 System.out.println(
"[类名+"+jp.getTarget().getClass().getName()+"],"+ "[方法名:"+jp.getSignature().getName()+"],"+ "[参数:"+jp.getArgs()[0]+"]"); }
//环绕通知,retVal是返回值。这里为null
public Object doAround(ProceedingJoinPoint pjp)throws Throwable{ System.out.println("doAround:加入前"); Object retVal= pjp.proceed(); System.out.println(retVal); System.out.println("doAround:加入后"); return retVal; } }

通过注解实现。

@Aspect
public class StudentServiceAspect {

    @Before(value="execution(* com.lufax.test.commen.studentService.*.addStudent(..)) ")
    public void doBefore(){
        System.out.println("类名:");
        System.out.println("doBefore:开始添加学生");
    }

    @After(value="execution(* com.lufax.test.commen.studentService.*.addStudent(..))")
    public void doAfter(JoinPoint jp){
        System.out.println("doAfter:添加完毕");
        System.out.println("[类名+"+jp.getTarget().getClass().getName()+"],"+
                           "[方法名:"+jp.getSignature().getName()+"],"+
                           "[参数:"+jp.getArgs()[0]+"]");
    }

    @Around(value="execution(* com.lufax.test.commen.studentService.*.addStudent(..))")
    public Object doAround(ProceedingJoinPoint pjp)throws Throwable{
        System.out.println("doAround:加入前");
        Object retVal= pjp.proceed();
        System.out.println(retVal);
        System.out.println("doAround:加入后");
        return retVal;
    }
}

最后写测试类。

@Test
    public void test_AopAspectJ() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","dataSource.xml");
        StudentService studentService = (StudentService) applicationContext.getBean("studentService");
        studentService.addStudent("张三");
    }

运行结果如下:

类名:
doBefore:开始添加学生
doAround:加入前
----正在添加张三----
doAfter:添加完毕
[类名+com.lufax.test.commen.studentService.StudentServiceImp],[方法名:addStudent],[参数:张三]
null
doAround:加入后

 

以上是关于Spring AOP理解的主要内容,如果未能解决你的问题,请参考以下文章

如何理解Spring的AOP?

Spring之AOP理解及使用

Spring-----AOP深度理解

Spring AOP的理解和使用

5 分钟理解 Spring 中的 AOP

Spring AOP理解