Spring学习笔记(十二)AOP的XML方式cglib代理-重点掌握
切点,切面,如何定义切点,前置、后置、放回、异常、环绕通知的XML版
源码获取github
1.项目结构(jar包跟上个一样)
2.核心业务代码
package com.hs.service;
/** * 对外提供的核心业务,完成了加法/减法/乘法运算 */
public interface ArithmeticService {
int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int div(int x, int y);
}
package com.hs.service.impl;
import com.hs.service.ArithmeticService;
import org.springframework.stereotype.Service;
/** * 核心代码 */
@Service
public class ArithmeticServiceImpl implements ArithmeticService {
@Override
public int add(int x, int y) {
//核心代码
int result = x + y;
return result;
}
@Override
public int sub(int x, int y) {
int result = x - y;
return result;
}
@Override
public int mul(int x, int y) {
int result = x * y;
return result;
}
@Override
public int div(int x, int y) {
int result = x / y;
return result;
}
}
3.切面
package com.hs.service.aspect;
import org.aspectj.lang.JoinPoint;
import java.util.Arrays;
//@Component
//@Aspect //标记这是切面
public class Logger {
public void test01() {
System.out.println("测试出order属性的作用");
}
//1.前置通知
public void test05(JoinPoint jp) {
//获取get
System.out.println("==前置通知==");
System.out.println(Arrays.asList(jp.getArgs()));
System.out.println(jp.getSignature().getName());
System.out.println(jp.getTarget().getClass().getName());
System.out.println("==前置通知==");
}
//2.后置通知
public void test06(JoinPoint jp) {
System.out.println("==后置增强==");
System.out.println(Arrays.asList(jp.getArgs()));
System.out.println(jp.getSignature().getName());
System.out.println(jp.getTarget().getClass().getName());
System.out.println("==后置增强==");
}
//3.返回通知
public void test07(JoinPoint jp, int hs) {
System.out.println("==返回通知==");
System.out.println("程序正常运行,正确的运行结果为==>" + hs);
System.out.println("==返回通知==");
}
//4.异常通知
public void test08(JoinPoint jp, ArithmeticException hs) {
System.out.println("==异常通知==");
System.out.println("程序运行错误==>" + hs);
System.out.println("==异常通知==");
}
}
4.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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<!--1.启动Spring注解-->
<context:annotation-config></context:annotation-config>
<!--2.扫描-->
<context:component-scan base-package="com.hs"/>
<!--Spring提供了多种AOP的实现方式,但是我们只用第三方的AOP标准-->
<!--3.启动AOP注解:false是使用默认的java代理,true是使用CGLIB代理-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!--4.AOP的XML配置方式,false是使用默认的java代理,true是使用CGLIB代理-->
<!--实例化那个类,在切面引用的时候好用-->
<bean id="logger" class="com.hs.service.aspect.Logger"/>
<bean id="logger111" class="com.hs.service.aspect.Logger"/>
<aop:config proxy-target-class="true">
<!--定义切点,可以把切点放在外面作为公共的,注意pointcut aspect的顺序,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>
<!--定义切面,对应注解版的@Aspect,order,定义切面的执行顺序,不写默认为从上到下执行-->
<aop:aspect ref="logger111" order="2">
<!--定义切点,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
<!--<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>-->
<aop:before method="test01" pointcut-ref="servicePointCut"/>
</aop:aspect>
<!--定义切面,对应注解版的@Aspect-->
<aop:aspect ref="logger" order="1">
<!--定义切点,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
<!--<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>-->
<aop:before method="test05" pointcut-ref="servicePointCut"/>
</aop:aspect>
</aop:config>
</beans>
首先得实例化
<bean id="logger" class="com.hs.service.aspect.Logger"/>
切点:
<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>
切面:
<aop:aspect ref="logger111" order="2">
<!--定义切点,对应注解版的@PointCut(value = "execution(* com.hs..service.*Service.*(..))")-->
<!--<aop:pointcut id="servicePointCut" expression="execution(* com.hs..service.*Service.*(..))"/>-->
<aop:before method="test01" pointcut-ref="servicePointCut"/>
</aop:aspect>
测试:
package com.hs.test;
import com.hs.service.ArithmeticService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ArithmeticServiceTest {
private ArithmeticService arithmeticService;
private ApplicationContext ac;
@Before
public void init() {
this.ac = new ClassPathXmlApplicationContext("beans.xml");
this.arithmeticService = this.ac.getBean("arithmeticServiceImpl", ArithmeticService.class);
}
@Test
public void testAddMethod() {
int result = this.arithmeticService.div(2,1);
System.out.println("运行的结果:"+ result);
}
}