理解面向切面编程
面向切面编程是软件编程思想发展到一定阶段的产物,
是对面向对象编程的有益的补充.
AOP一般适用于具有横切逻辑的场合,如访问控制,事务管理,性能检测等.
AOP的目标(作用):让我们可以“专心做事” 日志记录,事务处理,异常捕获,缓存操作。
AOP原理
将复杂的需求分解出不同方面,将散布在系统中的公共功能集中解决
采用代理机制组装起来运行,在不改变原程序的基础上对代码段进行增强处理,增加新的功能
面向切面编程的基本概念
切面(Aspect):一个模块化的横切逻辑,可能会横切多个对象
连接点(Join Point):程序执行中的某个具体的执行点.
增强处理(Advice):切面在某个特定的连接点上执行的代码逻辑
切入点(Pointcut):对连接点的特征进行描述,可以使用正则表达式.增强处理和一个切入点表达式相关联,并在这个切入点匹配的某个连接点上运行.
目标对象(Target object):被一个或者多个切面增强的对象.
AOP代理(AOP proxy):由AOP框架所创建的对象,实现执行增强处理方法等功能.
织入(Weaving):将增强处理连接到应用程序中的类型或对象上的过程.
增强处理类型:前置增强,后置增强,环绕增强,异常抛出增强,最终增强等类型
使用Spring AOP实现日志输出
新建一个类
package cn.baby.entity; /** * Created by Administrator on 2017/10/18. */ public class HelloSpring { private String who=null; public String getWho() { return who; } public void setWho(String who) { this.who = who; } //输出方法 public void print(){ System.out.println("Hello,"+this.getWho()+"!"); } }
写增强方法
package cn.baby.aop; import cn.baby.entity.HelloSpring; import org.aspectj.lang.JoinPoint; import sun.rmi.runtime.Log; import java.util.Arrays; import java.util.logging.Logger; /** * Created by Administrator on 2017/10/18. */ public class UserServiceLogger { private static final Logger log=Logger.getLogger(String.valueOf(UserServiceLogger.class)); //代表前置增强 public void before(JoinPoint jp){ log.info("我是日志"+jp.getTarget()+jp.getSignature().getName()+ Arrays.toString(jp.getArgs())); } //代表后置增强 public void afterReturning(JoinPoint jp,Object result){ log.info(jp.getTarget()+jp.getSignature().getName()+ result); } }
配置Spring配置文件
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd "> <!--通过bean元素声明需要Spring创建的实例.该实例属性的类型通过class属性来指定并通过id属性为实例指定一个名称,以便于访问--> <bean id="helloSpring" class="cn.baby.entity.HelloSpring"> <!--通过property元素用来为实例的属性赋值--> <property name="who"> <value>Spring</value> </property> </bean> <bean id="theLogger" class="cn.baby.aop.UserServiceLogger"></bean> <aop:config> <!--定义一个切入点表达式--> <aop:pointcut id="pointcut" expression="execution(public void print())"/> <!--将before()方法定义为前置增强并引用poincut切入点--> <aop:aspect ref="theLogger"> <aop:before method="before" pointcut-ref="pointcut"></aop:before> <!--将afterReturning()方法定义为后置增强并引用poincut切入点result作为参数--> <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/> </aop:aspect> </aop:config> </beans>
写测试类
@Test public void show() { //实例化Spring ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext-hello.xml"); //通过ApplicationContext的getBen方法,根据id来获取Bean的实例 HelloSpring hellospring = (HelloSpring) context.getBean("helloSpring"); hellospring.print(); }
结果图