Spring-aop面向切面编程笔记
1.需要引入的jar包
AOP功能是基于IOC的功能之上,所有需要先引入ioc的全部jar包
AOP和ASPECTS是构成AOP的基础,所有需引入这两个jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.25.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.25.RELEASE</version> </dependency>
2.名词解释
切入点:重复的代码,被加在其他方法前后的代码
切面:任何一个类,里面有多个切入点
关注点:目标,要加到哪里去,可以是一个方法、一个类的所有方法、一个包下的所有类
com.blb.Run.*(..)) 一个类的所有方法
execution(* com.blb..*(..)) 包下任意层
3.常用注释
@Aspect 把该类声明为切面
@Before :把方法在目标前执行
@Before("execution(* com.blb.Run.*(..))") 指定关注点
@After:同@Before
@AfterReturning:方法正常完成后执行
@AfterThrowing: 抛出增强(目标方法发生异常,执行)
@Around: 环绕增强(目标方法执行前后,分别执行一些代码)
@Pointcut:定义一个公用的切面表达式,其他方法只需用它修饰的方法名即可代替切面表达式
@Pointcut("execution(* com.blb.UserDao.*(..))") public void xiaohong(){ System.out.println("hello"); }
@After("xiaohong()") public void go(){ System.out.println("hou1"); } @After("xiaohong()") public void go2(){ System.out.println("hou2"); }
4.配置文件使用
引入的jar包只能用xml配置文件的方式加入ioc容器
使用aop切片也一样用到xml文件
aop:pointcut:是定义一个公用的pointcut(写目标位置)
<!-- 加入到ioc容器--> <bean id="hang" class="com.blb.Hang"></bean> <aop:config> <aop:aspect ref="hang"> <aop:pointcut id="xiaobai" expression="execution(* com.blb.UserDao.*(..))"/> <aop:before method="sayHello" pointcut-ref="xiaobai"></aop:before> <aop:after method="sayHello" pointcut="execution(* com.blb.UserDao.*(..))"/> </aop:aspect> </aop:config>
1. <aop:config> 作用:声明aop配置 2. <aop:pointcut> 作用:配置切入点表达式 属性:id:唯一标识切入点表达式名称 expression:定义切入点表达式 3. <aop:aspect> 作用:配置切面 属性:id:唯一标识切面的名称 ref:引用切面类(通知类)bean的id 4. <aop:before> 作用:配置前置通知(在执行目标对象方法之前执行) 属性:method:指定通知方法名称 pointcut:定义切入点表达式 pointcut-ref:引用切入点表达式的id。 5.<aop:returning> 作用:配置后置通知 属性:method:指定通知方法名称 pointcut:定义切入点表达式 point-ref:引用切入点表达式的id 6.<aop:after-throwing> 作用:配置异常通知 属性:method:指定通知方法名称 pointcut:定义切入点表达式 pointcut-ref:引用切入点表达式的id 7.<aop:after> 作用:配置最终通知 属性:method:指定通知方法名称 pointcut:定义切入点表达式 pointcut-ref:引用切入点表达式的id 8. <aop:around> 作用:配置环绕通知 属性:method:指定通知方法名称 pointcut:定义切入点表达式 pointcut-ref:引用切入点表达式的id
5.代码使用
applicationContext.xml文件:
<?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: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-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd "> <!--启用注解--> <context:annotation-config></context:annotation-config> <!--设置扫描范围--> <context:component-scan base-package="com.blb"></context:component-scan> <!--启用aop功能--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
log4j.properties:
log4j.rootLogger=INFO,Log4jConsole
log4j.appender.Log4jConsole=org.apache.log4j.ConsoleAppender
log4j.appender.Log4jConsole.Threshold=INFO
log4j.appender.Log4jConsole.ImmediateFlush=true
log4j.appender.Log4jConsole.Target=System.out
log4j.appender.Log4jConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.Log4jConsole.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss,SSS}]
切面类:
package com.blb; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import java.util.logging.Logger; @Component //加到ioc @Aspect //切面 public class Haha { private Logger logger= Logger.getLogger(String.valueOf(Haha.class)); @Before("execution(* com.blb.Run.*(..))") public void before(){ System.out.println("begin"); } @After("execution(* com.blb.Run.*(..))") public void after(){ System.out.println("end"); } @AfterThrowing("execution(* com.blb.Run.*(..))") public void exprission(){ System.out.println("你的代码发生了异常"); } @Around("execution(* com.blb.Mark.*(..))") public void around(ProceedingJoinPoint point){ logger.info(point.getSignature().getName()+"--------start");//获取类名 try { point.proceed(); //表示注入点方法 } catch (Throwable throwable) { throwable.printStackTrace(); } logger.info(point.getSignature().getName()+"--------end"); } }
注入点:
package com.blb; import org.springframework.stereotype.Component; @Component public class Run { public void hello() { System.out.println("nigao!"); } }
测试代码:
package com.blb; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AppTest { @Test public void getAOP(){ BeanFactory bf=new ClassPathXmlApplicationContext("applicationContext.xml"); Run run = (Run)bf.getBean("run"); run.hello(); } @Test public void getMark(){ BeanFactory bf=new ClassPathXmlApplicationContext("applicationContext.xml"); Mark mark=(Mark) bf.getBean("mark"); mark.say(); } }