小言_互联网的博客

Spring入门—SpringAop

287人阅读  评论(0)

一、springAop术语

springAop:面向切面编程。可插拔式的。即各个方法模块独立。需要就添加配置,不需要时就删除配置。

  1. 切面(Aspect):横切关注点被模块化的特殊对象,即要插入的功能。
  2. 通知(Advice):店面必须要完成的工作,所谓通知是指拦截到joinpoint之后要做的事情。
    • 通知分为:前置通知、后置通知、异常通知、最终通知、和环绕通知。
  3. 目标(target):被通知的对象。
  4. 代理(Proxy):向目标对象应用通知之后创建的对象。
  5. 连接点(JoinPoint):程序执行的某个特定位置。eg:类的某个方法运行前、调用后、方法抛出异常后等。
    • 连接点有两个信息要确定,一个是方法(程序执行点),即执行什么样的方法时需要连接。
    • 另一个就是方位(程序相对点),即在什么时候连接,是方法执行前、执行后还是抛出异常后等。
  6. 切点(PointCut):每个类都拥有多个连接点,那么切点就是用来定位到特殊连接点的。
    • 类比:连接点相当于数据库中的记录,而切点相当于查询条件。
  7. 织入(Weaving):是指把切面应用到目标对象来创建新的代理对象的过程,切面怎么指定的连接点织入到目标对象。
  8. 引入(Introduction):在不修改代码的前提下,Introduction可以在运行期为类动态的添加一些方法或Filed。

二、springAop快速入门—案例(这里使用注解方案)

1. 导入相关依赖包

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-beans</artifactId>
	<version>5.2.3.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.2.3.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aspects</artifactId>
	<version>5.2.3.RELEASE</version>
</dependency>

<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

2. 编写计算器接口(Calculator.java)

public interface Calculator {
	public int plus(int x, int y, int z);
	public double plus(double x, double y);
	public int plus(int x, int y);
	public int substract(int x, int y);
	public int division(int x,int y);
	public int multiplication(int x,int y);
}

3. 编写计算器类继承上面的接口(HxCalculator.java)

@Component		//這裏一定要加上注解,説明這是一個組件
public class HxCalculator implements Calculator{
	@Override
	public int plus(int x, int y, int z) {
		return x + y + z;
	}
	@Override
	public double plus(double x, double y) {
		return x + y;
	}
	@Override
	public int plus(int x, int y) {
		int result = x + y;
		return result;
	}
	@Override
	public int substract(int x, int y) {
		int result = x - y;
		return result;
	}
	@Override
	public int division(int x, int y) {
		int result = x / y;
		return result;
	}
	@Override
	public int multiplication(int x, int y) {
		int result = x * y;
		return result;
	}
}

4. 编写日志工具类(LogUtil.java)

public class LogUtil {
	public static Logger log = Logger.getLogger(LogUtil.class);
}

5. 编写日志切面类(LoggingAspect.java)

/**
 * 日志切面
 * @author Huathy
 * @date 2020年3月5日 
 */
@Order(1)		//如果同时有多个切面,可以通过@Order注解来解决切面的先后顺序,值越小优先级越高
@Component		//这个切面我们需要放到ioc容器中,所以需要加上注解@Componet
@Aspect			//将这个类声明为切面
public class LoggingAspect {
	/**
	 * 前置通知
	 * @param jp
	 */
	@Before("execution(public int com.hx.springaop.impl.HxCalculator.plus(int,int))")
	public void beforeMethod(JoinPoint jp){
		String methodName = jp.getSignature().getName();
		LogUtil.log.info( "前置通知-方法" + methodName + "開始執行,參數為" + Arrays.toString(jp.getArgs()) );
	}
	/**
	 * 后置通知
	 * @param jp
	 */
	@After("execution(public * com.hx.springaop.impl.HxCalculator.plus(..))")
	public void afterMethod(JoinPoint jp){
		String methodName = jp.getSignature().getName();
		LogUtil.log.info( "后置通知-方法" + methodName + "運行結束..." );
	}
	
	@Pointcut("execution(public * com.hx.springaop.impl.HxCalculator.*(..))")
	public void logging(){}
	
	/**
	 * 返回通知
	 * @param jp
	 * @param result
	 */
	@AfterReturning(value="logging()", returning="result")
	public void afterReturnMethod(JoinPoint jp,Object result){
		String methodName = jp.getSignature().getName();
		LogUtil.log.info( "返回通知-方法" + methodName + "運行結束,返回結果為:" + result );
	}
	/**
	 * 异常通知
	 * @param jp
	 * @param e
	 */
	@AfterThrowing(value="logging()", throwing="e")
	public void afterThrowMethod(JoinPoint jp, Exception e){
		String methodName = jp.getSignature().getName();
		LogUtil.log.info( "异常通知-方法" + methodName + "出現異常信息:" + e );
	}
	/**
	 * 环绕通知
	 * @param pjp
	 * @return
	 */
	@Around("logging()")
	public Object around(ProceedingJoinPoint pjp){
		Object obj = null;
		String methodName = pjp.getSignature().getName();
		LogUtil.log.info( "環繞通知-方法" + methodName + "開始執行,參數:" + Arrays.toString(pjp.getArgs()) );
		try {
			obj = pjp.proceed();	//运行方法
			LogUtil.log.info( "環繞通知-方法" + methodName + "運行結束,結果:" + obj );
		} catch (Throwable e) {
			LogUtil.log.info( "環繞通知-方法" + methodName + "運行出現異常信息:" + e );
			e.printStackTrace();
		}
		return obj;
	}
}

6. 在资源包下编写全局配置spring-beans.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:util="http://www.springframework.org/schema/util"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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/util
		http://www.springframework.org/schema/util/spring-util.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="com.hx.springaop" />
	
	<!-- 讓注解起作用 -->
	<aop:aspectj-autoproxy />
</beans>

7. 把log4j.properties放到资源包下

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  %m%n

log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=hx.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  %l  %m%n

log4j.rootLogger=debug, stdout, file

8. 编写测试类

public class AppTest {
	@Test
	public void test1(){
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");
		Calculator clt = (Calculator) context.getBean("hxCalculator");
		
		System.out.println( clt.plus(10, 20) );
		System.out.println( clt.plus(10, 20, 30) );
		System.out.println( clt.plus(10.1, 10.2) );
		System.out.println( clt.substract(10, 20) );
		System.out.println( clt.division(10, 0) );
	}
}

9. 项目目录结构

三、上述案例(xml配置方案)

1.把上面所有类上的通知组件等注解删除

2.修改spring-beans.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:util="http://www.springframework.org/schema/util"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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/util
		http://www.springframework.org/schema/util/spring-util.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">
	
	<!-- 计算器类 -->
	<bean id="calculator" class="com.hx.springaop.impl.HxCalculator"></bean>
	<!-- 切面类 -->
	<bean id="logAspect" class="com.hx.springaop.util.LoggingAspect"></bean>

	<!-- 配置aop -->
	<aop:config>
		<!-- 配置切点表达式 -->
		<aop:pointcut id="pointcut1" expression="execution(public int com.hx.springaop.impl.HxCalculator.plus(int,int))"></aop:pointcut>
		<aop:pointcut id="pointcut2" expression="execution(public * com.hx.springaop.impl.HxCalculator.*(..))"></aop:pointcut>
		
		<!-- 配置切面通知。ref:应用的切面id。 -->
		<aop:aspect ref="logAspect" order="1">
			<!-- 配置通知类型对应调用的方法以及切点 -->
			<aop:before method="beforeMethod" pointcut-ref="pointcut1"></aop:before>
			<aop:after method="afterMethod" pointcut-ref="pointcut2"></aop:after>
			<aop:after-returning method="afterReturnMethod" pointcut-ref="pointcut2" returning="result"></aop:after-returning>
			<aop:after-throwing method="afterThrowMethod" pointcut-ref="pointcut2" throwing="e"></aop:after-throwing>
			<aop:around method="around" pointcut-ref="pointcut2"></aop:around>
		</aop:aspect>
	</aop:config>
</beans>

3. 修改测试类

@Test
public void test1(){
	ApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");
	Calculator clt = (Calculator) context.getBean("calculator");
		
	System.out.println( clt.plus(10, 20) );
	System.out.println( clt.plus(10, 20, 30) );
	System.out.println( clt.plus(10.1, 10.2) );
	System.out.println( clt.substract(10, 20) );
	System.out.println( clt.division(10, 0) );
}

转载:https://blog.csdn.net/qq_40366738/article/details/104699572
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场