spring AOP——用代理+API实现

spring AOP——用代理和API实现

  • 目录
    • 说明
    • 项目的结构
    • 配置applicationContext.xml
    • 前置通知:BeforeAdvice.java
    • 环绕通知:CompareInterceptor.java
    • 后置通知:AfterAdvice.java
    • 异常通知:ThrowsAdvice.java
    • 目标对象的接口:IStudent.java
    • 目标对象类:StudentImpl.java
    • 测试类,MyText.java
    • 总结

目录

说明

AOP:面向切面编程,用匹配的方式来确定目标对象,用通知来对监视进行操作。
本例子不是web项目。

项目的结构

图片: spring AOP——用代理+API实现_第1张图片
spring AOP——用代理+API实现_第2张图片

配置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.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd">


	<!-- 定义AOP通知的类,硬编码方式实现AOP -->
	<!-- 前置通知 -->
	<bean id="beforeAdvice" class="text3_AOP_text1.BeforeAdvice"></bean>
	<!-- 使用拦截器实现环绕通知 -->
	<bean id="compareInterceptor" class="text3_AOP_text1.CompareInterceptor"></bean>
	<!-- 返回后通知 -->
	<bean id="afterAdvice" class="text3_AOP_text1.AfterAdvice"></bean>
	<!-- 异常通知 -->
	<bean id="throwsAdvice" class="text3_AOP_text1.throwsAdvice"></bean>
	
	<!-- 定义AOP连接点,在代理目标中匹配调用的方法 -->
	<bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
		<property name="mappedNames">
			<!-- 匹配目标对象中方法的类型 -->
			<list>
				<value>add*</value>
			</list>
		</property>
	</bean>

	<!-- 定义AOP切面,精细化操作到方法 -->
	<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<!-- 加入连接点 -->
		<property name="pointcut" ref="pointcutBean" />
		<!-- 加入通知类型 -->
		<property name="advice" ref="beforeAdvice"/>
		
	</bean>
	

	<!-- 目标 对象 -->
	<bean id="studenttarget" class="text3_AOP_text1.StudentImpl"></bean>


	<!-- spring 的代理工厂类,"像被代理对象被劫持了" -->
	<bean id="baseProxyBean" class="org.springframework.aop.framework.ProxyFactoryBean"
		lazy-init="true" abstract="true"></bean>

	<!-- 继承代理工厂bean -->
	<bean id="student" parent="baseProxyBean">
		<!-- 被代理对象实现的接口 -->
		<property name="proxyInterfaces">
			<value>text3_AOP_text1.IStudent</value>
		</property>
		<!-- 被代理对象 -->
		<property name="target">
			<ref bean="studenttarget" />
		</property>
		<!-- 像被代理对象进行的监视和限制的手段 -->
		<property name="interceptorNames">
			<!-- 加入的通知类型 -->
			<list>
				<value>defaultAdvisor</value>
				<value>beforeAdvice</value>
				<value>compareInterceptor</value>
				<value>afterAdvice</value>
				<value>throwsAdvice</value>
			</list>
		</property>
	</bean>
	
</beans>

说明:
实现AOP的API方式,实现通知的接口来表示通知类型的,使用代理的方式来实现面向切面
提醒:
1. 在定义AOP切面bean时,是不能使用list的

前置通知:BeforeAdvice.java

前置通知:BeforeAdvice.java,代码片.

package text3_AOP_text1;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
/**
 *@author dragon 前置通知:BeforeAdvice.java
 */
public class BeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		System.out.println("这是前置通知@BeforeAdvice类的before方法 : " 
							+ method.getName() + "     " 
							+ target.getClass().getName());
	}
}

说明:
[Method method, Object[] args, Object target]=[传值目标方法,参数,目标对象]

环绕通知:CompareInterceptor.java

环绕通知:CompareInterceptor.java,代码片.

package text3_AOP_text1;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
 * @author dragon 环绕通知:CompareInterceptor.java
 */
public class CompareInterceptor implements MethodInterceptor {

	public Object invoke(MethodInvocation invocation) 
			throws Throwable {
		
		Object result = null;//返回值
		String stu_name = invocation.getArguments()[0].toString();// invocation是传递方法调用关系的参数,获得调用的方法的第一个参数
		
		if (stu_name.equals("dragon")) {// 如果学生是dragon时,执行目标方法,
			System.out.println("这里是环绕前 @此学生是" + stu_name 
							+ "批准其加入.调用的方法名是:" + invocation.getMethod().getName());
			
			result = invocation.proceed();// 执行text中调用的方法
			
			System.out.println("这里是环绕后 @此学生是" + stu_name 
							+ "批准其加入.调用的方法名是:" + invocation.getMethod().getName());
		} else {
			System.out.println("此学生是" + stu_name + "而不是dragon,不批准其加入.");
		}
		
		return result;
	}
}

说明:
[MethodInvocation invocation]
=[联系上下文]

后置通知:AfterAdvice.java

后置通知:AfterAdvice.java,代码片.

package text3_AOP_text1;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
/**
 * @author dragon 后置通知:AfterAdvice.java
 */
public class AfterAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object returnValue, Method method, 
			Object[] args, Object target) throws Throwable {
		System.out.println("这是后置通知@AfterAdvice类的afterReturning方法.调用方法是:" 
							+ method.getName() + "     "
							+ target.getClass().getName() + "       " 
							+ returnValue);
	}
}

说明:
[Object returnValue, Method method, Object[] args, Object target]
=[返回值,传值目标方法,参数,目标对象]

异常通知:ThrowsAdvice.java

异常通知:ThrowsAdvice.java,代码片.

package text3_AOP_text1;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
/**
* @author dragon 异常通知:ThrowsAdvice.java
 */
public class throwsAdvice implements ThrowsAdvice {
	
//	public void afterThrowing(Exception ex) throws Throwable {
//		System.out.println("MoocThrowsAdvice afterThrowing 1");
//	}
	
	//异常通知,传值目标方法,参数,目标对象,异常类型
	public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
		System.out.println("MoocThrowsAdvice afterThrowing 2 : " + method.getName() + "       " + 
				target.getClass().getName());
	}

}

说明:
[Method method, Object[] args, Object target, Exception ex]
=[传值目标方法,参数,目标对象,异常类型]
从上面类代码可以看出,方法的参数可以自己选定,spring会自动加载

目标对象的接口:IStudent.java

目标对象的接口:IStudent.java,代码片.

package text3_AOP_text1;
/**
 *  @author 目标对象的接口:IStudent.java 
 */
public interface IStudent {
	public void addStudent(String name);
}

目标对象类:StudentImpl.java

目标对象类:StudentImpl.java,代码片.

package text3_AOP_text1;
/**
 * @author 目标类:StudentImpl.java
 */
public class StudentImpl implements IStudent {
	public void addStudent(String name) {
		System.out.println(" 欢迎  " + name + "  你加入Spring家庭! ");
	}
}

测试类,MyText.java

测试类,MyText.java,代码片.

package text3_AOP_text1;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
/**
 * @author 测试类,MyText.java
 */
@RunWith(BlockJUnit4ClassRunner.class)
public class MyText extends UnitTestBase {
	public MyText() {
   		super("text3_AOP_text1/applicationContext.xml");
   	}

	@Test
	public void test() {
//		ApplicationContext ctx = new ClassPathXmlApplicationContext("text3_AOP_text1/applicationContext.xml");
		IStudent person = (IStudent) super.getBean("student");
		person.addStudent("dragon");// 传入名字
//		person.addStudent("javadragon");
	}
}

说明:
使用了Junit.jar,还使用了spring,测试类UnitTestBase.java(略)。
提示
也可以不使用测试包,用主方法来调用代码如下:

public static void main(String[] args) {
		ApplicationContext context=new 
						ClassPathXmlApplicationContext(
								"text3_AOP_text1/applicationContext.xml");
		IStudent person = (IStudent) context.getBean("student");
		person.addStudent("dragon");// 传入名字
	}

总结

	1. 使用API来实现功能,都是通过继承或者实现框架内定义的功能类和功能接口来办到的,和注解和配置一样,都是注册的一种标识。
**引用包是最大的困难(一步一步来)**

你可能感兴趣的:(spring,AOP,spring,AOP,AOP,面向切面编程,spring,API)