Spring学习笔记4——AOP
AOP 即 Aspect Oriented Program 面向切面编程
首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。
所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务
所谓的周边功能,比如性能统计,日志,事务管理等等
周边功能在Spring的面向切面编程AOP思想里,即被定义为切面
在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发
然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP
第一步:思路图
1. 功能分两大类,辅助功能和核心业务功能
2. 辅助功能和核心业务功能彼此独立进行开发
3. 比如登陆功能,即便是没有性能统计和日志输出,也可以正常运行
4. 如果有需要,就把"日志输出" 功能和 "登陆" 功能 编织在一起,这样登陆的时候,就可以看到日志输出了
5. 辅助功能,又叫做切面,这种能够选择性的,低耦合的把切面和核心业务功能结合在一起的编程思想,就叫做切面编程
第二步:准备业务类
ProductService.java
1 package com.spring.service; 2 3 public class ProductService { 4 public void doSomeService() { 5 System.out.println("doSomeService"); 6 } 7 }
第三步:测试(TestSpring)
没有引入切面之前,调用该业务类
1 package com.spring.test; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 import com.spring.service.ProductService; 7 8 public class TestSpring { 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" }); 13 14 ProductService s = (ProductService) context.getBean("Pservice"); 15 s.doSomeService(); 16 } 17 18 }
第四步:准备日志切面 LoggerAspect
该日志切面的功能是 在调用核心功能之前和之后分别打印日志,切面就是原理图中讲的那些辅助功能。
1 Object object = joinPoint.proceed();
这一句代码就是将来与某个核心功能编织之后,用于执行核心功能的代码
LoggerAspect.java
1 package com.spring.aspect; 2 3 import org.aspectj.lang.ProceedingJoinPoint; 4 5 public class LoggerAspect { 6 public Object log(ProceedingJoinPoint joinPoint) throws Throwable { 7 System.out.println("start log:" + joinPoint.getSignature().getName()); 8 Object object = joinPoint.proceed(); 9 System.out.println("end log:" + joinPoint.getSignature().getName()); 10 return object; 11 } 12 }
第五步:修改applicationContext.xml
1.声明业务对象
1 <bean name="Pservice" class="com.spring.service.ProductService"> 2 </bean>
2.声明日志切面
1 <bean name="loggerAspect" class="com.spring.aspect.LoggerAspect"> 2 </bean>
3.结合
<1>指定右边的核心业务功能
1 <aop:pointcut expression="execution(* com.spring.service.ProductService.*(..))" id="loggerCutpoint"/>
<2>指定左边的辅助功能
1 <aop:aspect id="logAspect" ref="loggerAspect"> 2 <aop:around pointcut-ref="loggerCutpoint" method="log"/> 3 </aop:aspect>
<3>然后通过aop:config把业务对象与辅助功能编织在一起。
1 <aop:config> 2 <aop:pointcut expression="execution(* com.spring.service.ProductService.*(..))" id="loggerCutpoint"/>
3 <aop:aspect id="logAspect" ref="loggerAspect"> 4 <aop:around pointcut-ref="loggerCutpoint" method="log"/> 5 </aop:aspect> 6 </aop:config>
注:(注意“*”后面的空格)
execution(* com.spring.service.ProductService.*(..))
这表示对满足如下条件的方法调用,进行切面操作:
* 返回任意类型
com.spring.service.ProductService.*
包名以com.spring.service.ProductService 开头的类的任意方法
(..) 参数是任意数量和类型
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xmlns:context="http://www.springframework.org/schema/context" 7 xsi:schemaLocation=" 8 http://www.springframework.org/schema/beans 9 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 10 http://www.springframework.org/schema/aop 11 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 12 http://www.springframework.org/schema/tx 13 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 14 http://www.springframework.org/schema/context 15 http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 16 17 <!-- <context:annotation-config/>--> 18 <bean name="category" class="com.spring.cate.Category"> 19 <property name="name" value="category 3333" /> 20 </bean> 21 <bean name="product" class="com.spring.cate.Product"> 22 <property name="name" value="product 3333" /> 23 <property name="category" ref="category" /> 24 </bean> 25 <bean name="Pservice" class="com.spring.service.ProductService"> 26 </bean> 27 28 <bean name="loggerAspect" class="com.spring.aspect.LoggerAspect"> 29 </bean> 30 <aop:config> 31 <aop:pointcut expression="execution(* com.spring.service.ProductService.*(..))" id="loggerCutpoint"/> 32 <aop:aspect id="logAspect" ref="loggerAspect"> 33 <aop:around pointcut-ref="loggerCutpoint" method="log"/> 34 </aop:aspect> 35 </aop:config> 36 </beans>
第六步:TestSpring
TestSpring 代码没有发生任何变化,通过配置的方式,把切面和核心业务类编制在了一起。
运行测试,可以发现在编织之后,业务方法运行之前和之后分别会打印日志
TestSpring.java
1 package com.spring.test; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 import com.spring.service.ProductService; 7 8 public class TestSpring { 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" }); 13 ProductService s = (ProductService) context.getBean("Pservice"); 14 s.doSomeService(); 15 } 16 17 }