所以,感觉很多知识不懂的时候,觉得那个东西特别难特别牛逼,当你明白了以后,发现原来也没神马大不了的。
我觉得学习这些东西先从简单的应用例子开始,然后再慢慢的体会理论上的东西才是正确的方法。
所以,要学懂Spring 的AOP,我们也从简单的例子开始吧。下面是一个简单的环绕型Advice的例子。
情景:我们要调用某个业务逻辑类的某个方法,并且需要在调用方法之前做一些其他处理,比如打个日志之类的,然后调用业务逻辑方法,调用结束后我们又想做一些其他事情,比如还是打一条日志。这样我们就可以用注入环绕型通知的方式来完成了,这一点和Struts2的拦截器非常相似,几乎一样。
1、新建业务逻辑接口
package leon.springaop.iface;
public interface UserDao {
public String getUserList();
}
2、业务逻辑接口实现类,也就是真实的业务逻辑类
package leon.springaop.impl;
import leon.springaop.iface.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void getUserList() {
System.out.println("UserDaoImpl-getUserList()...");
System.out.println("get User List form database...");
}
}
3、环绕型通知(调用方法之前和之后要做的事情在这里定义)
package leon.springaop.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//Around拦截器实现MethodInterceptor接口
public class AroundInterceptor implements MethodInterceptor {
// 实现MethodInterceptor接口必须实现invoke方法
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before business logic...");
Object rval = invocation.proceed();
System.out.println("After business logic...");
return rval;
}
}
4、Spring的bean配置文件,比如 springaop.xml
主要配置三个东西:
(1) 将真实业务实现类配置成为bean
(2) 将Advice类配置成为 bean
(3) 配置真实业务逻辑代理
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="userDao" class="leon.springaop.impl.UserDaoImpl" />
<bean id="myAroundInterceptor" class="leon.springaop.advice.AroundInterceptor" />
<bean id="userProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="leon.springaop.iface.UserDao"/>
<property name="target" ref="userDao" />
<property name="interceptorNames">
<list>
<value>myAroundInterceptor</value>
</list>
</property>
</bean>
</beans>
说明:业务逻辑代理,使用了org.springframework.aop.framework.ProxyFactoryBean,这是个代理工厂bean,该bean主要注入3个变量proxyInterfaces, target, interceptorNames,其中interceptorNames是拦截器,也是通知,属List类型,可以注入多个拦截器,也就是添加多个value,这样就会按先后顺序进行层层递归拦截。
5、调用测试
package leon.springaop.test;
import leon.springaop.iface.UserDao;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class TestAround {
public static void main(String[] args) {
Resource rsc = new ClassPathResource("springaop.xml"); //这种方式springaop.xml保存在工程源文件目录下
BeanFactory bf = new XmlBeanFactory(rsc);
UserDao userProxy = (UserDao)bf.getBean("userProxy");
userProxy.getUserList(); //proxy invoke the business logic
}
}
运行这个类:
Before business logic...
UserDaoImpl-getUserList()...
get User List form database
After business logic...
OK,效果出来了。
现在你可以翻开书,或者其他资料去看看那些连接点,切点,切面等概念了,很容易的。
另外,Advice除了上面的环绕型通知,还有前置型、后置型、抛异常,共4种。
每种Advice的定义都是要集成相应的类或者实现相应的接口。
比如上面的环绕型Advice实现了MethodInterceptor接口。