Aop( aspect oriented programming ) 面向切面(方面)编程,是对所有对象或者是一类对象编程,核心是( 在不增加代码的基础上, 还增加新功能 )
步骤:
1. 定义接口
2. 编写对象(被代理对象=目标对象)
3. 编写通知(前置通知目标方法调用前调用)
4. 在beans.xml文件配置
4.1 配置 被代理对象=目标对象
4.2 配置通知
4.3 配置代理对象 是 ProxyFactoryBean的对象实例
4.3.1 <!-- 代理接口集 -->
4.3.2 织入通知
4.3.3 配置被代理对象
切面:交叉功能
织入:把交叉功能织入到Proxy对象
连接点->切入点
通知:
前置通知,后置通知,环绕通知,异常通知,引入通知
实例如下:
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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 配置被代理对象,配置前置通知对象,配置代理对象 -->
<bean id="Test1Service" class="com.hsp.aop.Test1Service">
<property name="name" value="lv" />
</bean>
<bean id="MyMethodBeforeAdvice" class="com.hsp.aop.MyMethodBeforeAdvice">
</bean>
<!-- 配置后置通知 -->
<bean id="MyMethodAfterAdvice" class="com.hsp.aop.MyMethodAfterAdvice">
</bean>
<!-- 配置环绕通知 -->
<bean id="HuanRaoTongZhi" class="com.hsp.aop.HuanRaoTongZhi">
</bean>
<bean id="MyThrowsAdvice" class="com.hsp.aop.MyThrowsAdvice"></bean>
<!-- 引入通知 定义切入点 -->
<bean id="LeadIntoMyAdvice" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="MyMethodBeforeAdvice"></property>
<property name="mappedNames">
<list>
<value>sayBye</value>
</list>
</property>
</bean>
<bean id="ProxyFactoryBean1" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<!-- 代理接口集 -->
<list>
<value>com.hsp.aop.TestServiceInterface</value>
<value>com.hsp.aop.TestServiceInterface2</value>
</list>
</property>
<!-- 把通知织入到代理对象 -->
<property name="interceptorNames">
<list>
<!-- 前置对象和代理对象关联起来 ,可以把通知看成拦截器 -->
<!-- <value>MyMethodBeforeAdvice</value> -->
<!-- 后置通知和代理对象关联起来,可以把 -->
<value>MyMethodAfterAdvice</value>
<value>HuanRaoTongZhi</value>
<value>MyThrowsAdvice</value>
<!-- 使用自定义切入点控制 前置通知 -->
<value>LeadIntoMyAdvice</value><!-- 前置通知指定sayHello 把前置去掉,生成前置 -->
</list>
</property>
<!--配置 被代理对象 -->
<property name="target" ref="Test1Service" />
</bean>
</beans>
接口
public interface TestServiceInterface {
void sayHello();
}
接口2
public interface TestServiceInterface2 {
void sayBye();
}
继承类
public class Test1Service implements TestServiceInterface,TestServiceInterface2{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("hello my lover sayHello()"+name);
//System.out.println(8/0);
}
public void sayBye() {
System.out.println("I am the interface2 sayBye()"+name);
}
}
前置通知
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
/*
* method被调用的方法名
* args给方法传递的参数有哪些
* target 调用该方法的目标对象
* 代理对象只需配置不需要写,使用到动态代理技术
* @see org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
*/
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
// TODO Auto-generated method stub
System.out.println(" 前置通知 目前没有记录日志 哪个方法被调用"+method.getName());
}
}
后置通知
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
public class MyMethodAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println("后置通知资源已经关闭"+method.getName());
}
/*
* method被调用的方法名
* args给方法传递的参数有哪些
* target 调用该方法的目标对象
* 代理对象只需配置不需要写,使用到动态代理技术
* @see org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
*/
}
环绕通知
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class HuanRaoTongZhi implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
// TODO Auto-generated method stub
System.out.println(" 调用前"+arg0.getMethod());
Object o=arg0.proceed();
System.out.println("调用后");
return o;
}
}
异常通知
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class MyThrowsAdvice implements ThrowsAdvice {
/*public void afterThrowing(Throwable throwable)
{
}*/
public void afterThrowing(Method m, Object args, Object target,
Throwable subclass) {
System.out.println("[DaoThrowsAdvice]: An exception occur: "
+ subclass.getClass().getSimpleName()+":"+subclass.getMessage());
System.exit(0);
}
}
测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ac=new ClassPathXmlApplicationContext("com/hsp/aop/beans.xml");
/*Test1Service te=(Test1Service) ac.getBean("Test1Service");
te.sayHello();*/
TestServiceInterface pfb=(TestServiceInterface) ac.getBean("ProxyFactoryBean1");
//TestServiceInterface2 pfb1=(TestServiceInterface2) ac.getBean("ProxyFactoryBean1");
/*
* pfb:Spring Aop中当你通过代理对象去实现Aop技术的时候,获取的proxyFactorybean是什么类型
* 返回的是一个代理对象,如果目标对象实现了接口,则Spring使用jdk的动态代理技术完成
* 如果目标对象没有实现接口,则Spring使用CGlib的动态代理技术完成
*/
//切入点可以用正则表达式匹配
System.out.println("pfb类型是"+pfb);
pfb.sayHello();
((TestServiceInterface2)ac.getBean("ProxyFactoryBean1")).sayBye();
//pfb1.sayBye();
//引入通知自定义切入点
}
}