spring学习笔记(三) spring AOP 切点拦截 ——yibai

  • Spring AOP : 面向方面(切面)编程,用于在模块化方面的横切关注点。

可以简单的理解为spring提供了拦截器,用来拦截一些过程。比如一个方法执行前,执行返回结果后,执行抛出异常后。添加额外的处理(通知)

在Spring AOP中,有 4 种类型通知(advices)的支持:

  • 通知(Advice)之前 - 该方法执行运行

    • 实现 MethodBeforeAdvice 接口 , 并配置 bean , 通过 代理对象 进行拦截

  • 通知(Advice)返回之后 – 运行,该方法返回一个结果

    • 实现 AfterReturningAdvice 接口

  • 通知(Advice)抛出之后 – 运行方法抛出异常后

    • 实现 ThrowsAdvice 接口

  • 环绕通知 – 环绕方法执行运行,结合以上这三个通知。
    • TODO 未知原因没后实现 

以上四种配置bean方法基本类似

实例(通知(Advice)之前):

userServiceBean

package tao.test.service;

public class UserService {
	private String uName;
	private int uAge;

	public String getuName() {
		return uName;
	}
	public void setuName(String uName) {
		this.uName = uName;
	}
	public int getuAge() {
		return uAge;
	}
	public void setuAge(int uAge) {
		this.uAge = uAge;
	}

	public void printName(){
		System.out.println("Name");
	}
}

HijackBeforeMethod

package com.cn.utils;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
 * @author Tao
 * @since 2019/01/14
 *
 */
public class HijackBeforeMethod implements MethodBeforeAdvice
{
	@Override
	public void before(Method method, Object[] args, Object target)
		throws Throwable {
	        System.out.println("HijackBeforeMethod : Before method !");
	        System.out.println("------------------------------");
			System.out.println("参数:" + args.toString());
			System.out.println("参数:" + target);
			System.out.println("------------------------------");
	}
}

 applicationContext.xml (部分 --上面两个java和代理的配置)

<bean id="userServiceBean" class="tao.test.service.UserService" />

	<!-- ************************************************************************************************* -->
	<bean id="hijackBeforeMethodBean" class="com.cn.utils.HijackBeforeMethod"></bean>

	<!-- 代理对象1 方法执行之前 -->
	<bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />
		<property name="interceptorNames">
			<list>
				<value>hijackBeforeMethodBean</value>
			</list>
		</property>

	</bean>

	<!-- ************************************************************************************************* -->

applicationContext.xml (全部 -- 包括后面两种方法的配置  和 拦截单个方法的配置(此部分可以忽略))

<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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<bean id="customerService" class="tao.test.service.CustomerService">
		<property name="name" value=" Tao " />
		<property name="url" value="www.kcss.com.cn" />
		<property name="userService" ref="userServiceBean"></property>
	</bean>
	<bean id="userServiceBean" class="tao.test.service.UserService" />

	<!-- ************************************************************************************************* -->
	<bean id="hijackBeforeMethodBean" class="com.cn.utils.HijackBeforeMethod"></bean>

	<!-- 代理对象1 方法执行之前 -->
	<bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />
		<property name="interceptorNames">
			<list>
				<value>hijackBeforeMethodBean</value>
			</list>
		</property>

	</bean>

	<!-- ************************************************************************************************* -->

	<bean id="hijackAfterMethodBean" class="com.cn.utils.HijackAfterMethod" />

	<!-- 代理对象2 方法返回结果之后 -->
	<bean id="customerServiceProxyAfter" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />
		<property name="interceptorNames">
			<list>
				<value>hijackAfterMethodBean</value>
			</list>
		</property>

	</bean>

	<!-- ************************************************************************************************* -->

	<bean id="HijackThrowExceptionBean" class="com.cn.utils.HijackThrowException"></bean>

	<!-- 代理对象 拦截抛出异常后 -->
	<bean id="customerServiceProxyThrowAfter" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />
		<property name="interceptorNames">
			<list>
				<value>HijackThrowExceptionBean</value>
			</list>
		</property>

	</bean>

	<!-- ************************************************************************************************* -->

	<!-- 通过“切入点”和“advisor”拦截printName()方法。 创建NameMatchMethodYiibaicut切入点bean,并提出要在“mappedName”属性值来拦截方法名。 -->
	<bean id="customerPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
		<property name="mappedName" value="printName" />
	</bean>


	<!-- 创建 DefaultYiibaicutAdvisor 通知 bean,通知和切入点相关联。 -->
	<bean id="customerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<property name="pointcut" ref="customerPointcut" />
		<property name="advice" ref="hijackAfterMethodBean" />
	</bean>

	<!-- 创建代理 -->
	<bean id="customerServiceProxyByName" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />
		<property name="interceptorNames">
			<list>
				<value>customerAdvisor</value>
			</list>
		</property>
	</bean>

	<!-- 方法2 使用 NameMatchMethodPointcutAdvisor 可以减少一个bean 配置, 它将 name 和 advice
		放在一起配置了 -->
	<bean id="customerAdvisor2"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="mappedName" value="printName" />
		<property name="advice" ref="hijackAfterMethodBean" />
	</bean>

	<!-- 创建代理 -->
	<bean id="customerServiceProxyByName2" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />
		<property name="interceptorNames">
			<list>
				<value>customerAdvisor2</value>
			</list>
		</property>
	</bean>

	<!-- ************************************************************************************************* -->

	<!-- 通过使用正则表达式匹配切入点方法的名称 – RegexpMethodPointcutAdvisor. -->
	<bean id="regexpMethodPointcutAdvisorBean"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="patterns">
			<list>
				<value>.*URL.*</value>
			</list>
		</property>
		<property name="advice" ref="hijackBeforeMethodBean" />
	</bean>



	<bean id="customerServiceProxyByEl" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />
		<property name="interceptorNames">
			<list>
				<value>regexpMethodPointcutAdvisorBean</value>
			</list>
		</property>
	</bean>

	<!-- ************************************************************************************************* -->
</beans>

App.java  测试类

package tao.test.test;

import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import tao.test.service.CustomerService;

/**
 * 测试类
 *
 * @since 2019/01/14
 * @author b1707007
 *
 */
public class App {

	/**
	 *
	 * 直接执行方法,没有拦截
	 */
	@Test
	public void test1() {
		AbstractApplicationContext appContext = new ClassPathXmlApplicationContext(
				new String[] { "applicationContext.xml" });

		CustomerService cust = appContext.getBean(CustomerService.class, "customerService");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");

		try {
			cust.printThrowException();
		} catch (Exception e) {
			System.out.println("出错啦! : " + e);
		} finally {
			appContext.close();
		}
	}

	/**
	 * AOP CustomerService 所有方法执行前都会先执行 HijackBeforeMethod.before(); 之前通知:
	 * 在方法调用时,进行拦截,在方法执行之前进行通知(处理)
	 *
	 * @author b1707007
	 */
	@Test
	public void test2() {
		AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");

		CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxy");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");

		try {
			cust.printThrowException();
		} finally {
			appContext.close();
		}
	}

	/**
	 * CustomerService 所有方法执行前都会先执行 HijackAfterMethod.afterReturning(); 之后通知:
	 * 在方法调用时,进行拦截,在方法执行之后进行通知(处理)
	 */
	@Test
	public void test3() {

		AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");

		CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxyAfter");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");

		try {
			cust.printThrowException();
		} finally {
			appContext.close();
		}
	}

	/**
	 * 拦截,方法执行抛出异常后 通知
	 */
	@Test
	public void test4() {
		AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxyThrowAfter");
		System.out.println("*************************");
		try {
			cust.printThrowException();
		} finally {
			appContext.close();
		}
	}

	/**
	 * 按名称匹配拦截的方法--切入点
	 */
	@Test
	public void test5() {
		AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxyByName");
		try {
			System.out.println("url: *************************");
			cust.printURL();
			System.out.println("*************************");

			cust.printName();
			System.out.println("*************************");
		} finally {
			appContext.close();
		}
	}

	/**
	 * 按正则表达式匹配拦截的方法--切入点
	 */
	@Test
	public void test6() {
		AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxyByEl");
		try {

			System.out.println("url: *************************");
			cust.printURL();
			System.out.println("url:*************************");

			cust.printName();
			System.out.println("*************************");
		} finally {
			appContext.close();
		}
	}

	/**
	 * 按名称匹配拦截的方法--切入点
	 * 配置方法2
	 */
	@Test
	public void test7(){
		AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxyByName2");
		try {
			System.out.println("url: *************************");
			cust.printURL();
			System.out.println("*************************");

			cust.printName();
			System.out.println("*************************");
		} finally {
			appContext.close();
		}
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值