AOP(Aspect Oriented Programming)面向切面编程
通过预编译方式和运行期动态代理实现程序功能的横向多模块统一控制的一种技术。AOP是(面向对象)OOP的补充,是Spring框架中一个重要的概念和内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP可以分为静态织入与动态织入,静态织入即在编译前将需织入内容写入目标模块中,这样成本非常高。动态织入则不需要改变目标模块。Spring框架实现了AOP,使用注解配置完成AOP比使用XML配置要更加方便与直观。
1.XML方式配置的Spring AOP:
在pom.xml文件中增加:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency>
---
public class ServiceFlow{ public String serviceMethod(String a, int b){ System.out.println("ServiceMethod invoked"); return a + b; } }
----
import org.aspectj.lang.JoinPoint; /** * Created by LG on 2017/1/1. * 通知类,横切逻辑 */ public class Advices{ public void before(JoinPoint jp){ System.out.println("----------前置通知----------method:"+jp.getSignature().getName()); } public void after(JoinPoint jp){ System.out.println("----------最终通知----------method:"+jp.getSignature().getName()); } }
----
springsop.xml
<?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:p="http://www.springframework.org/schema/p" 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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 被代理对象 --> <bean id="serbean" class="cn.luan.aop.ServiceFlow"></bean> <!-- 通知 --> <bean id="advices" class="cn.luan.aop.Advices"></bean> <!-- aop配置 --> <aop:config proxy-target-class="true"> <!--切面 --> <aop:aspect ref="advices"> <!-- 切点 --> <aop:pointcut expression="execution(* cn.luan.aop.ServiceFlow.*(..))" id="pointcut"/> <!--连接通知方法与切点 --> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> </aop:aspect> </aop:config> </beans>
--
测试类
public class Test{ public static void main(String[] args){ ApplicationContext ctx = new ClassPathXmlApplicationContext("springsop.xml"); ServiceFlow ser = ctx.getBean("serbean", ServiceFlow.class); ser.serviceMethod("haha", 100); } }
--
运行结果:
2.使用注解方式配置Spring AOP
修改如下代码:
@Service("serbean") public class ServiceFlow{ public String serviceMethod(String a, int b){ System.out.println("ServiceMethod invoked"); return a + b; } }
---@Aspect表示声明一个切面;@Before表示函数为前置通知,通过参数execution声明一个切点
@Component @Aspect public class Advices{ @Before("execution(* cn.luan.aop.ServiceFlow.*(..))") public void before(JoinPoint jp){ System.out.println("----------前置通知----------method:"+jp.getSignature().getName()); } @After("execution(* cn.luan.aop.ServiceFlow.*(..))") public void after(JoinPoint jp){ System.out.println("----------最终通知----------method:"+jp.getSignature().getName()); } }
spring.xml----增加aop:aspectj-autoproxy节点,Spring会自动为与AspectJ切面配置的Bean创建代理,proxy-target-class="true"表示被代理的目标对象是一个类,而非实现了接口的类。
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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"> <context:component-scan base-package="cn.luan.aop"> </context:component-scan> <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> </beans>
--测试类不变,运行结果不变
end