面向切面
- 原理:AOP(Aspect Oriented Programming)在不增加代码的基础上增加新的功能,将多种类要实现的公共功能抽象出来,形成自己的功能代码。也可以说是将交叉的功能(切面)独立出来,再交由需要该功能的类对象调用(织入)。
- 案例:调用函数记录日志。
- 想法:
- 提取出公共功能,形成类;
- 搭建起公共类与要调用类的桥;
- 借助公共接口实现类间联系;
- 使用通知,进行原过程点的拦截;
- 引入代理ProxyFactoryBean,帮助实现功能(织入)。
- 实现:
- Spring提供了自己的规范,通知类型为专有类型,分别为:
- 前置通知:进入方法之前被调用。
- 后置通知:方法使用之后被调用。
- 环绕通知:方法前后均被调用。
- 异常通知:存在异常时被调用。
- 引入通知:
- 具体代码:
写入通知MyMethodBeforeAdvice.java
package com.aop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
//继承前置通知接口
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
//参数含义:被调用等方法名,方法传递的参数,目标对象
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("记录日志"+arg0.getName());
}
}
配置代理:
先建立公共接口ParentInterface.java
package com.aop;
public interface ParentInterface {
public void sayhello();
}
继承类Testone.java
package com.aop;
public class Testone implements ParentInterface {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void sayhello() {
System.out.print("one hello"+name);
}
}
beans.xml
<!-- 要写入注解对象 -->
<bean id="testone" class="com.aop.Testone">
<property name="name" value="小红"></property>
</bean>
<!-- 前置通知对象 -->
<bean id="myMethodBeforeAdvice" class="com.aop.MyMethodBeforeAdvice" />
<!-- 代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 引入接口,搭建桥梁 -->
<property name="proxyInterfaces">
<list>
<value>com.aop.ParentInterface</value>
</list>
</property>
<!-- 引入通知 -->
<property name="interceptorNames">
<list>
<value>myMethodBeforeAdvice</value>
</list>
</property>
<!-- 目标对象-->
<property name="target" ref="testone" />
</bean>
测试代码Test.java
package com.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("com/aop/beans.xml");
ParentInterface emp=(ParentInterface) ac.getBean("proxyFactoryBean");
//接口获取,该过程完成通知织入
emp.sayhello();
//调用织入后的函数,完成目标
}
}