- AOP
即面向切面编程。
1.1 AOP中关键性概念
连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
目标(Target):被通知(被代理)的对象
注1:完成具体的业务逻辑
通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)
注2:完成切面编程
代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),
例子:外科医生+护士
注3:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的
切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。
(也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)
1.2如何实现AOP
目标对象只负责业务逻辑代码
通知对象负责AOP代码,这二个对象都没有AOP的功能,只有代理对象才有
上实例:
spring-context代码
<bean class="com.aop.impl.BookBizImpl" id="bookbiz"></bean>
<!-- 前置通知 -->
<bean class="com.aop.advice.Mymethodadvice" id="mymethodadvice"> </bean>
<!-- 生成代理 -->
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="myproxy">
<property name="target" ref="bookbiz"></property>
<!--生产出的代理必定要实现目标对象所实现的接口 -->
<property name="proxyInterfaces">
<list>
<value>com.aop.biz.BookBiz</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>mymethodadvice</value>
</list>
</property>
</bean>
advice类
package com.aop.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.MethodBeforeAdvice;
public class Mymethodadvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
String targername=target.getClass().getName();
String methodname=method.getName();
String params=Arrays.toString(args);
String msg="【系统日志:】"+targername+"."+methodname+",携带了参数"+params;
System.out.println(msg);
}
}
接口bookbiz
package com.aop.biz;
public interface BookBiz {
// 购书
public boolean buy(String userName, String bookName, Double price);
// 发表书评
public void comment(String userName, String comments);
}
bookbizimpl
package com.aop.impl;
import com.aop.biz.BookBiz;
import com.aop.ex.PriceException;
public class BookBizImpl implements BookBiz {
public boolean buy(String userName, String bookName, Double price) {
// 通过控制台的输出方式模拟购书
if (null == price || price <= 0) {
throw new PriceException("book price exception");
}
System.out.println(userName + " buy " + bookName + ", spend " + price);
return true;
}
public void comment(String userName, String comments) {
// 通过控制台的输出方式模拟发表书评
System.out.println(userName + " say:" + comments);
}
}
测试类
package com.aoptest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.aop.biz.BookBiz;
public class Aoptest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");
BookBiz bookBiz = (BookBiz) applicationContext.getBean("myproxy");
bookBiz.buy("海鳖","道君", 30d);
bookBiz.comment("海鳖","难受");
}
}
运行结果
【系统日志:】com.aop.impl.BookBizImpl.buy,携带了参数[海鳖, 道君, 30.0]
海鳖 buy 道君, spend 30.0
【买书返利日志:】com.aop.impl.BookBizImpl.buy,携带了参数[海鳖, 道君, 30.0],目标对象的返回值true
【系统日志:】com.aop.impl.BookBizImpl.comment,携带了参数[海鳖, 难受]
海鳖 say:难受
【买书返利日志:】com.aop.impl.BookBizImpl.comment,携带了参数[海鳖, 难受],目标对象的返回值null