这是传说中的黎活明老师的课程,该课程网上有免费视频下载。之前提到的巴巴运动网项目就是黎活明老师一个人一手开发的(巴巴运动网在线首页),以前是传智播客的必授课程,现在改为Android开发课程,还是黎老师授课。Android开发课程视频因为考虑到学员就业竞争力和培训机构之间竞争力的问题,暂不对外公布,想学习Android 3G开发的话欢迎来传智播客亲自聆听,而且传智播客现在特别推出了为期一周的Android 3G独立项目课程。
前面写hibernate的回调和拦截的时候,提到了一点点AOP的知识,现在才要开始动真格了。
何谓AOP
AOP(Aspect Oriented Programming),面向切面编程,理解AOP需要理解以下一些概念:
1、Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象。横切性关注点包括思考拦截什么方法,拦截后进行什么样的处理这样的思考步骤。
2、joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上AOP传统实现里的joinpoint还可以是field或类构造器)。
3、Pointcut(切入点):所谓切入点是指我们要对哪些joinpoint进行拦截的定义。
4、Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(spring里面实现了环绕通知的话,前面的几种通知方式可以在环绕通知方式里面手动实现)。
5、Target(目标对象):代理的目标对象。
6、Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入。
7、Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类(这个类指代理对象)动态地添加一些方法或Field。
模拟AOP实现
1、新建一个java项目,不引入任何框架(因为不是web项目,所以拦截不能使用过滤器,而且这个不是讨论的主题)。
2、假定一个业务逻辑:
(1)拦截所有业务方法;
(2)拦截以后,判断某用户是否有权限执行某方法,假设判断条件为:user属性是否为null。(在这一条假设编写代码实现的时候,最简单的方式是if判断,但是这种方式在企业应用中显然是不行的:一、造成代码冗余;二、不易于后期更改和维护;想象一下有成千上万个业务方法的时候吧)
NOTE:(1)和(2)即属于横切性关注点的范畴。
(3)代理。代理分为静态代理和动态代理,企业开发大多使用后者,所以这里模拟的也是后者。AOP中用户直接操作的往往是代理对象。动态代理指不用直接生成目标对象,只要生产代理对象的字节码即可。
(4)使用JDK里的Proxy:java.lang.reflect.Proxy,使用该类创建代理对象的前提的“目标对象”必须要实现一个接口,而且要使用Proxy的类一般要实现InvocationHandler接口,以通过invoke方法实现回调:
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
invoke(Object proxy, Method method, Object[] args);
(5)使用第三方工具类创建代理对象:cglib。cglib允许“目标对象”不用实现接口,不过利用cglib里的Enhancer创建代理对象之前,需要给其设置一个父类--即“目标对象”。cglib产生的代理类继承了目标类,并且覆写了父类所有非final的方法。
下面是使用cglib工具模拟的AOP实现(使用JDK自带Proxy实现的方式请参见前文):
public class CGlibProxyFactory implements MethodInterceptor{
private Object targetObject;
public Object createProxyIntance(Object targetObject){
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.targetObject.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
PersonServiceBean2 bean = (PersonServiceBean2)targetObject;
Object resutl = null;
if(bean.getUser() != null){
resutl = method.invoke(targetObject, args);
}
return resutl;
}
}
关于spring的更多知识,欢迎来传智播客亲自聆听:)