AOP:面向切面编程,用匹配的方式来确定目标对象,用通知来对监视进行操作。
本例子不是web项目。
,代码片
.
<?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,代码片
.
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,代码片
.
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,代码片
.
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,代码片
.
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,代码片
.
package text3_AOP_text1;
/**
* @author 目标对象的接口:IStudent.java
*/
public interface IStudent {
public void addStudent(String name);
}
目标对象类: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,代码片
.
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来实现功能,都是通过继承或者实现框架内定义的功能类和功能接口来办到的,和注解和配置一样,都是注册的一种标识。
**引用包是最大的困难(一步一步来)**