Spring AOP的 前置、环绕、后置、异常4种通知的简单实现

资料:

      

   首先,简单介绍一下AOP:即面向切面编程,可以说是OOP(面向对象编程)的补充和完善。

  它利用一种称为“横切”的技术,刨解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,命名为“切面”。

       所谓“切面”:简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

下面用一个简单的登录来解释4种通知:

 1、创建一个用户登录的 抽象类(接口)

public interface IPerson {

	/**
	 * 
	 * @Title: login
	 * @Description: 登录的方法
	 * @param userName
	 * @return void
	 */
	public void login(String userName);

}

2、创建一个用户登录的 真实的类(实现类):继承IPerson的接口

public class XiaoMing implements IPerson {

	@Override
	public void login(String userName) {
		//判断:如果输入的值不为“张三”,则进入异常处理
		if ("张三".equals(userName)) {
			System.out.println(userName + " 正在登录系统");
		} else {
			throw new RuntimeException("用户名不正确");
		}
	}

}

3、创建一个用户登录的   前置通知的类: 实现MethodBeforeAdvice接口             

public class BeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] objs, Object object) throws Throwable {
		String userName = (String) objs[0]; // 获取登录名
		System.out.println("用户 " + userName + " 登录前处理");
	}

}

创建一个用户登录的    后置通知的类: 实现AfterReturningAdvice接口    

public class AfterAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		String userName = (String) args[0]; // 获取登录名
		System.out.println(userName + " 登录成功");
	}

}

创建一个用户登录的    环绕通知的类: 实现MethodInterceptor接口    

public class SurroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {

		Object[] objs = invocation.getArguments();
		String userName = (String) objs[0];
		// 在目标方法执行前调用
		System.out.println("正在对" + userName + "进行登录验证");
		// 通过反射调用执行方法
		Object obj = invocation.proceed();
		// 在目标方法执行之后调用
		System.out.println(userName + "登录成功");

		return obj;
	}

}

创建一个用户登录的    异常通知的类: 实现ThrowsAdvice接口    

public class ExceptionAdvice implements ThrowsAdvice {
	public void afterThrowing(Method method, Object[] objs, Object target, Exception ex) {
		System.out.println("登录名错误");
	}
}

4、配置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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">


	<!-- 1、配置目标 -->
	<bean id="xm" class="com.zking.springProxy.XiaoMing">
	</bean>


	<!-- 前置通知 -->
	<bean id="beforeAdvice" class="com.zking.springProxy.BeforeAdvice"></bean>

	<!-- 后置通知 -->
	<bean id="afterAdvice" class="com.zking.springProxy.AfterAdvice"></bean>

	<!-- 环绕通知 -->
	<bean id="surroundAdvice"
		class="com.zking.springProxy.SurroundAdvice"></bean>

	<!-- 异常通知 -->
	<bean id="exceptionAdvice"
		class="com.zking.springProxy.ExceptionAdvice"></bean>


	<!-- 配置通知的过滤 -->
	<bean id="myInform"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<!-- 引用前置通知 -->
		<property name="advice" ref="beforeAdvice"></property>
		<!-- 在方法调用的时候,会调用前置通知 -->
		<!-- 以.*开头,.*结尾,中间写的是 方法名包含的内容 -->
		<property name="pattern" value=".*eat.*"></property>
	</bean>

	<!-- 配置混合代理对象 -->
	<bean id="myProxy"
		class="org.springframework.aop.framework.ProxyFactoryBean">

		<!-- 2、引用目标 :target原对象,目标 -->
		<property name="target" ref="xm"></property>

		<!-- 3、目标实现的所有的接口 -->
		<property name="proxyInterfaces">
			<list>
				<value>com.zking.springProxy.IPerson</value>
			</list>
		</property>


		<!-- 引用通知 -->
		<property name="interceptorNames">
			<list>
				<!-- 引用前置通知 -->
				<!-- <idref bean="beforeAdvice" /> -->
				<idref bean="myInform" />
				<!-- 引用后置通知 -->
				<idref bean="afterAdvice" />
				<!-- 引用环绕通知 -->
				<idref bean="surroundAdvice" />
				<!-- 引用异常通知 -->
				<idref bean="exceptionAdvice" />
			</list>
		</property>
	</bean>

</beans>

5、创建一个测试类:

public class PersonTest {

	@Test
	public void test() {
		//得到配置文件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		//创建接口
		IPerson ip = (IPerson) applicationContext.getBean("myProxy");
		//调用登录的方法
		// ip.login("张三");
		ip.login("李四");
	}

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值