AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
大白话来说就是,面向对象解决了层次的问题,比如下级继承上级来增强上级等等。AOP解决了左右级问题,比如分别给一下不同的对象的某些方法加入不同的额外功能等等。特点是通过代理方式对目标类在运行期间织入功能。
这些关键词配置会用到要记住
大概过程:先要定义一个切入点来设置在哪些方法进行拦截,然后写出切面并在这里对拦截到的连接点进行一些操作比如权限判断等,最后动态生成一个增强类。
5中类型实现方法基本上差不多,
举个很简单的栗子:通过xml配置
三个增强类
参数类型主要有,目标类方法的返回值,目标类方法的名称,目标方法的参数等
public class MyAfterReturningAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("后置通知,返回值是:"+returnValue);
}
}
public class MyMethodBeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("前置增强");
}
}
public class MyMethodInterceptor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("环绕通知1");
Object result = invocation.proceed();
System.out.println("环绕通知2");
return result;
}
}
测试:
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans3.xml");
TableServiceI tableServiceI= (TableServiceI) applicationContext.getBean("tableServicePro");
tableServiceI.add();
}
大致过程:加载xml文件,获取动态代理类,动态代理类返回一个增强类,增强类调用方法时会执行织入的增强方法
解决办法:1.使用动态代理方式(配置好自动生成代理类),2.配置切入点(配置在哪些方法进行切入)
也可以选择默认自动生成动态代理
Spring新版已经将Aspect整合到Core包中了,AspectJ1.5之后可以直接用注解形式进行配置更方便
差不多就是切入点一样的概念
举个栗子:
配置xml,开启自动代理,目标类和代理类
代理类:切入点用缺省语句来,方便简单
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyAspect {
@Before("execution(* com.baidu.beans4..*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("前置增强:"+joinPoint);
}
@AfterReturning(value="execution(* com.baidu.beans4..*(..))",returning="reval")
public void myAfterReturning(JoinPoint joinPoint,Object reval) {
System.out.println("后置增强:"+joinPoint+"--"+reval);
}
@Around(value="execution(* com.baidu.beans4..add*(..))")
public void myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕增强1:"+joinPoint);
Object proceed = joinPoint.proceed();
System.out.println("环绕增强2:"+joinPoint+"--"+proceed);
}
@After(value="execution(* com.baidu.beans4..add*(..))")
public void myAfter(JoinPoint joinPoint) throws Throwable{
System.out.println("最终通知:"+joinPoint);
}
}
目标类
public class StudentServiceImpl implements StudentServiceI{
@Override
public void delete() {
System.out.println("delete");
}
@Override
public String add() {
System.out.println("add");
return "add";
}
}
接口类
public interface StudentServiceI {
void delete();
String add();
}
测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans7.xml");
StudentServiceI studentServiceI=(StudentServiceI) applicationContext.getBean("studentServiceImpl");
studentServiceI.add();
studentServiceI.delete();
}
}
需要将代理类里的注解全部去掉:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspect {
public void before(JoinPoint joinPoint) {
System.out.println("前置增强:"+joinPoint);
}
public void myAfterReturning(JoinPoint joinPoint,Object reval) {
System.out.println("后置增强:"+joinPoint+"--"+reval);
}
public void myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕增强1:"+joinPoint);
Object proceed = joinPoint.proceed();
System.out.println("环绕增强2:"+joinPoint+"--"+proceed);
}
public void myAfter(JoinPoint joinPoint) throws Throwable{
System.out.println("最终通知:"+joinPoint);
}
}
并在Xml里配置: