AOP基本概念:
Aspect(切面):通常是一个类,里面可以定义切入点和通知JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,aroundPointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式AOP代理:
AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类Procy代理:将通知应用到目标对象之后,被动态创建的对象。Weaving织入:将切面代码插入到目标对象上,从而生成代理对象的过程JDK动态代理:
JDK动态代理是通过java.lang.reflect.Proxy类来实现的,我们可以调用Proxy类的newProxyInstance(方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现AOP。CGLIB代理:
CGLIB(Code Generation Library)是一个高性能开源的代码 生成包,它采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。AOP的用途:
权限的校验日志的记录事务的处理性能的检测AOP通知方法:
前置通知:在我们执行目标方法之前运行(@Before)后置通知:在我们目标方法运行结束之后,不管有没有异常(@After)返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)环绕通知:动态代理,需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知, 执行之后就相当于我们后置通知(@Around)切点表达式:
修饰关键字:public private protectd,一般这个写*,表示不限定关键词返回值类型:int string Person void,一般省略不写(如果要写,修饰关键词不能*)切入点属于哪个包,配置包名,必须写完整的包名,不支持子包切入点属于哪个类,配置类名,如果*,表示不限定切入点是哪个方法,配置方法名切入点方法的参数,一般用两个点表示任意参数都可以几个例子:
execution(public * *(…)) :
pulbic开头的任意包的任意类的任意方法,任意返回值,任意参数execution(* set*(…)):
任意修饰的任意包的任意类的以set开头的方法,任意返回值,任意的参数execution(* com.xyz.service.AccountService.*(…)):
任意修饰的com.xyz.service包的AccountService类的任意方法,任意返回值,任意的参数execution(* com.xyz.service..(…)):
任意修饰的com.xyz.service包的任意类的任意方法,任意返回值,任意的参数execution(* com.xyz.service….(…)):
任意修饰的com.xyz.service包(包括所有的子包)的任意类的任意方法,任意返回值,任意的参数 ProxyFactoryBean ProxyFactoryBean是FactoryBean接口的实现类,FactoryBean负责实例化一个Bean,而ProxyFactoryBean负责为其他Bean创建代理实例。在Spring中,使用ProxyFactoryBean是创建AOP代理的基本方式。 实现AOP基于XML实现添加依赖
创个接口(UserDao.java)
创建一个实现类,UserDaorel02.java实现上面的接口
配置文件application.xml
创建一个实现AOP的类MyAspect类
创建一个测试类,测试一下这个接口和AOP是否成功结果测试成功。
基于注解实现 添加依赖编写配置文件 <?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:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 设置包扫描 --> <context:component-scan base-package="example04" /> <!-- 设置开启AOP注解 --> <aop:aspectj-autoproxy /> </beans> 编写接口 public interface Service { public void save(); public void delete(); public void update(); public int query(); public void batch(); } 编写实现类,实现接口 @Service public class UserDaorel02 implements UserDao { @Override public void save() { System.out.println("执行save"); } @Override public void delete() { System.out.println("执行delete"); } @Override public void update() { System.out.println("执行update"); } @Override public int query() { System.out.println("执行query"); return 100; } @Override public void batch() { System.out.println("执行batch"); } } 编写代理类 @Component // 使用@Aspect表示这个类就是切面类 @Aspect public class MyProxy { /** * 定义前置通知 */ @Before("execution(* save*(..))") public void saveMethodProxy() { System.out.println("执行之前进行权限校验"); } /** * 定义后置通知 */ @AfterReturning(value = "execution(* query*(..))") public void afterMethodProxy() { System.out.println("我是后置通知"); } /** * 定义环绕通知 * * @throws Throwable */ @Around(value = "execution(* update*(..))") public void aroundMethodProxy(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("我是环绕通知,在之前执行"); // 通过执行proceed方法才会执行我们目标类中的方法 joinPoint.proceed(); System.out.println("我是环绕通知,在之后执行"); } /** * 异常通知 * * @throws Throwable */ @AfterThrowing(value = "execution(* delete*(..))") public void exceptionMethodProxy(){ System.out.println("我是异常通知,在出现异常的时候执行"); } /** * 最终通知 * * @throws Throwable */ @After(value = "execution(* batch*(..))") public void afterMethodProxy2() { System.out.println("我是最终通知,就算程序有异常,也会执行"); } } 最后写个测试方法测试一下 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "classpath:applicationContext2.xml") public class TestUserDao { @Autowired private PeopleService peopleService; @Test public void testSaveMethod() { this.peopleService.save(); this.peopleService.query(); this.peopleService.update(); this.peopleService.delete(); this.peopleService.batch(); } }