SpringAOP面向切面编程使用测试(使用schema配置方式)
首先来举例什么是AOP(面向切面编程)。
大家都知道实现代码重用的一种方式是继承,继承可以解决很多的问题。来看一张继承的图片。
可以发现继承侧重点在竖直方向上。
但是在做开发的时候也会遇到下面一种继承无法解决的问题,那就是业务代码(以下例子中Service代表业务代码)被非业务代码(以下例子中Other代表非业务代码)所包围,从而导致了代码的参杂和程序耦合度的提高。非业务代码一般指日志记录、性能监控、安全监测等。这样会导致如果想要实现几个业务,同时每个业务都需要日志记录、性能监控、安全监测等功能,那么有多少个业务程序,就需要写多少次非业务代码,非常的不方便,代码大量冗余。而AOP面向切面编程就是从横向抽取业务逻辑来解决这个问题。AOP就是将这些重复冗余的代码抽取出来(切面),然后在使用的时候再切进去,切点就是需要切入位置,例如下面例子中切点就是service.startService();
如图:
具体实现如下:
第一步、
创建配置文件:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
</beans>
第二步、
先创建业务逻辑类,非业务逻辑类(这里利用简洁的实例来模拟)
非业务逻辑类:
package cn.zzcfirst;
public class Other {
public void startOther() {
System.out.println("监视器等非业务逻辑代码");
}
}
业务逻辑类:
package cn.zzcfirst;
public class Service {
public void startService() {
System.out.println("业务逻辑代码");
}
}
主类:
package cn.zzcfirst;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
private static final String FILE_NAME = "ApplicationContext.xml";
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Service service = (Service)context.getBean("service");
/*
* 非面向切面编程代码
* other.startOther();
* service.StartService();
* other.startOther();
*/
//面向切面编程代码
service.startService();
}
}
第三步、
创建通知类:
通知类的作用就是将需要的代码整合在方法中,需要的时候进行调用。
package zzc.advice;
import org.aspectj.lang.JoinPoint;
import cn.zzcfirst.Other;
public class myAdvice {
private Other other;
public myAdvice() {}
public void setOther(Other other) {
this.other = other;
}
public void before(JoinPoint joinpoint) {
other.startOther();
}
public Object afterReturnning(JoinPoint joinpoint,Object returnValue) {
other.startOther();
return returnValue;
}
}
第四步、
将通知类以及其他业务非业务类添加到IoC容器中:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<bean id="service" class="cn.zzcfirst.Service">
</bean>
<bean id="other" class="cn.zzcfirst.Other">
</bean>
<bean id="myadvice" class="zzc.advice.myAdvice">
<property name="other">
<ref bean="other"></ref>
</property>
</bean>
<aop:config>
<aop:pointcut expression="execution(public void cn.zzcfirst.Service.startService())" id="pointcut"/>
<aop:aspect ref="myadvice">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturnning" pointcut-ref="pointcut" returning="returnValue"/>
</aop:aspect>
</aop:config>
</beans>
测试执行结果:
使用AOP的结果和原代码结果相同。