首页 > 代码库 > Spring AOP理解

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; }}

通过注解实现。

@Aspectpublic 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],[参数:张三]nulldoAround:加入后

 

Spring AOP理解