1、经典的基于代理的AOP实现,用的是一个helloworld为例:
(1)先定义一个接口,任何可以说“helloworld”的类都可以实现它。
public interface HelloWorld {
void printHelloWorld();
void doPrint();
}
(2)定义两个接口实现类。
public class HelloWorldImpl1 implements HelloWorld {
public void printHelloWorld() {
System.out.println("------11111------按下HelloWorld1.printHelloWorld()-----11111111-------");
}
public void doPrint() {
System.out.println("------1111111------打印HelloWorldImpl1-----1111111------");
return ;
}
}
public class HelloWorldImpl2 implements HelloWorld {
public void printHelloWorld() {
System.out.println("------222222------按下HelloWorld2.printHelloWorld()------2222222------");
}
public void doPrint() {
System.out.println("-------22222-----打印HelloWorldImpl2------22222-----");
return ;
}
}
(3)HelloWorld的两个实现类关注的是业务逻辑,但在此之外还需要其他的功能逻辑等,如打印时间、打印日志等等。这里开始就需要AOP替“HelloWorldImpl”完成!解耦!首先需要一个TimeHandler类。因为一个是切入点前执行、一个是切入点之后执行,所以实现对应接口。
横切关注点,这里是打印时间:
public class TimeHandler implements MethodBeforeAdvice, AfterReturningAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("代理----前----CurrentTime = " + System.currentTimeMillis());
}
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("代理----后----CurrentTime = " + System.currentTimeMillis());
}
}
(3)最关键的来了,Spring核心配置文件application.xml配置AOP
<?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.xsd
">
<!-- 定义被代理者 -->
<bean id="h1" class="com.lym.aopTest.HelloWorldImpl1"></bean>
<bean id="h2" class="com.lym.aopTest.HelloWorldImpl2"></bean>
<!-- 定义通知内容,也就是切入点执行前后需要做的事情 -->
<bean id="timeHandler" class="com.lym.aopTest.TimeHandler"></bean>
<!-- 定义切入点位置,这里定义到了doPrint方法上 -->
<bean id="timePointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*doPrint"></property>
</bean>
<!-- 使切入点与通知相关联,完成切面配置 -->
<bean id="timeHandlerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="timeHandler"></property>
<property name="pointcut" ref="timePointcut"></property>
</bean>
<!-- 设置代理 -->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的对象,有打印时间能力 -->
<property name="target" ref="h1"></property>
<!-- 使用切面 -->
<property name="interceptorNames" value="timeHandlerAdvisor"></property>
<!-- 代理接口,hw接口 -->
<property name="proxyInterfaces" value="com.lym.aopTest.HelloWorld"></property>
</bean>
<!-- 设置代理 -->
<bean id="proxy2" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的对象,有打印时间能力 -->
<property name="target" ref="h2"></property>
<!-- 使用切面 -->
<property name="interceptorNames" value="timeHandlerAdvisor"></property>
<!-- 代理接口,hw接口 -->
<property name="proxyInterfaces" value="com.lym.aopTest.HelloWorld"></property>
</bean>
<!--<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>-->
</beans>
(5)测试类,Test,其中,通过AOP代理的方式执行h1、h2,其中doPrint()方法会把执行前、执行后的操作执行,实现了AOP的效果!
public class Test {
public static void main(String[] args){
//@SuppressWarnings("resource")
//如果是web项目,则使用以下代码加载配置文件,如果是一般的Java项目,则使用注释的方式
ApplicationContext appCtx = new ClassPathXmlApplicationContext("conf/application.xml");
//ApplicationContext appCtx = new FileSystemXmlApplicationContext("conf/application.xml");
HelloWorld hw1 = (HelloWorld) appCtx.getBean("proxy");
HelloWorld hw2 = (HelloWorld) appCtx.getBean("proxy2");
hw1.printHelloWorld();
System.out.println();
hw1.doPrint();
System.out.println();
hw2.printHelloWorld();
System.out.println();
hw2.doPrint();
}
}