一.体验AOP
1.首先定义一个接口IService
public interface IService {
void say();
}
2.定义Service类实现IService
public class Service implements IService{
@Override
public void say() {
System.out.println("现在是say方法");
}
}
3.定义一个AOP方法
public class Aop {
public void doAop(){
System.out.println("这里是Aop方法");
}
}
4.定义一个通知AopAdvice
public class AopAdvice implements MethodBeforeAdvice, AfterReturningAdvice {
private Aop aop;
@Override
public void before(Method method, Object[] os, Object o) throws Throwable {
aop.doAop();
}
@Override
public void afterReturning(Object o, Method method, Object[] os, Object o1) throws Throwable {
aop.doAop();
}
public void setAop(Aop aop) {
this.aop = aop;
}
}
5.在第四步操作时,在AopAdvice这个通知里有一个aop的引用,因此要使用到Spring的的依赖注入。并且AOP里面的切面,通知器,代理都是依靠Spring的DI。因此,这里我们需要一个Spring容器去管理,所以就有了接下来的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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
" xmlns:aop="http://www.springframework.org/schema/aop">
<!--切面 通知器 代理都是spring的DI自动注入的-->
<!--所以这里需要一个Springxml文件去创建一个Spring容器,让容器管理以上-->
<bean id="service" class="aopcarla.Service"></bean>
<bean id="aop" class="aopcarla.Aop"></bean>
<!--通知-->
<!--在aopadvice里面使用aop对象-->
<bean id="aopAdvice" class="aopcarla.AopAdvice">
<property name="aop" ref="aop"></property>
</bean>
<!--切点-->
<bean id="aopPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<!--使用正则表达式去找到一个对应的切点-->
<property name="pattern" value=".*say.*"/>
</bean>
<!--将切点和通知注入给通知器-->
<bean id="aopAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="aopAdvice"/>
<property name="pointcut" ref="aopPointcut"/>
</bean>
<bean name="aopProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--目标:service.-->
<property name="target" ref="service"/>
<!--代理需要通知的通知器-->
<property name="interceptorNames" value="aopAdvisor"/>
<!--接口-->
<property name="proxyInterfaces" value="aopcarla.IService"/>
</bean>
</beans>
service是主进程
aop是方面/切面
aopPointcut是切点,由于使用了aop引用,所以用property去设值注入。这也是为什么在AopPointcut里有setAop()方法。(事实上就是new了一个Aop)
AopAdvisor是通知器
AopProxy是代理,其中target是目标(主进程由谁实现:这里是谁实现我们的say()方法)。interceptorNames是通知器,proxyInterfaces是接口。
6.接下来创建Aop类实现
public class Aopcarla {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("aopcarla/ac.xml");
//基于接口接收一个代理
IService service=(IService)context.getBean("aopProxy");
// 事实上这里是代理调用主程序
service.say();
}
}
ClassPath是我们第五步创建的Spring的ac.xml文件路径
如上结果成功
二.什么是AOP
AOP(Aspect Oriented Programming),面向切面/方面编程。
简单来说,AOP是可以动态的插入一些代码到指定的地方,而不影响源代码的技术。
举个例子:A,B,C是三个方法,他们执行顺序如下:
假设现在有一个Logger()方法,该方法需要在A,B,C方法的执行前后去执行,如下图所示
本来主程序A,B,C是顺序执行。但加入Logger()后,每一个方法好像是被切了一刀。因此AOP被称为面向切面编程。
AOP的优点
根据上述的举例,不难发现AOP的优点:
使业务逻辑各个部分耦合性降低,提高程序的可重用性。
减少重复代码,提高开发效率,便于维护。
三.AOP的组件:
通知:方面执行的操作。就本例来说。切面就是Aop()方法。就通知简单来说,在我看来,就是决定要使用哪个方面,方面的位置在哪里等等。(运行哪一个辅程序?该辅程序放在哪里?)
连接点:应用程序的点或位置,可以插入通知。就是切面可以插入的地方。任何一个方法都是连接点。像例子中的A,B,C以及上述的Say()方法。
切入点:通知应该应用于哪个连接点。真正插入了切面的连接点。
目标:切面应用到的对象。具体哪个对象去实现了该切面。service这个对象是最终实现了我们的方法。
代理:简单来说,代理就是:我让你帮我去银行取10元,你可以在取钱之前逛街买衣服,在取完钱之后洗澡睡觉,但无论如何最终你把10元取来并给我,就可以了。
织入:指定连接点将切面应用到目标对象以创建新的被代理对象的过程。
四.AOP的整个流程
因此,在使用AOP时,需要接口,实现接口的类,切面,通知。而切点,通知器,代理都是依靠Spring的DI。