简单认识 Spring AOP

 对于SpringAOP的学习,是一个比较有趣的东西,要充分认识他,你就必须充分认识代理模式,因为Spring里面的AOP基本都是通过jdk的动态代理模式来实现的。
    代理模式的精髓就是,你自己要干的事情,你不干了,叫你的代理帮你做了。代理模式分为两种动态代理和静态代理。
    回味一下静态代理:所谓的静态代理就是提前就已经存在了,就有点像static一样,不是通过运行的时候才产生的。基本的步骤是这样子的:一个接口两个类。本来是这样的如果在定义一个接口以后,我们有一个类去实现了里面的所有方法,这个时候突然需要加点东西,比如说写日志啊,安全性检查啊这些。这些功能是跟本来的业务没有任何关系的,他们是不相互影响的。那么这个时候你可以选择写一个公共方法,

然后在每个方法的第一句话来调用这个方法,但是这样违背了我们ooad的ocp原则,所以我们要采用代理模式,静态代理的核心是,实现与被代理类相同的接口,因为你要代理谁你并不知道,所以你还必须拥有被代理类的引用。这样你在代理类里面把该做的就做了,以后要用的时候就直接用代理类就可以了。这样没有破坏我们的ocp原则,也实现了我们想要的功能。具体代码如下:
接口类:
package com.lovo.json.bean;

public interface UserManager {
 
 public void add(String name, String password);

 public void del(int id);

 public String find(int id);
}
实现类:也就是被代理类:
package com.lovo.json.bean;

public class UserManagerImp implements UserManager {

 public void add(String name, String password) {
  
  System.out.println("-------add---------");
 }

 public void del(int id) {
 
  System.out.println("-------del---------");
 }

 public String find(int id) {
  
  System.out.println("-------find---------");
  return null;
 }
 
// private void salf(){
//  System.out.println("--------salf------");
// }

}
最后就是代理类:
package com.lovo.json.bean;

public class UserManagerImpProxy implements UserManager {
 
 private UserManager userManager;
 
 public UserManagerImpProxy(UserManager userManager){
  this.userManager = userManager;
 }
 
 public void add(String name, String password) {
  
   salf();
   userManager.add(name, password);
 }

 public void del(int id) {
  
   salf();
   userManager.del(id);
 }

 public String find(int id) {
  //这个方法没有安全性检查,所以在运行的时候不调养salf方法
  
  
  return userManager.find(id);
 }
 
 private void salf(){
  System.out.println("--------salf------");
 }
 
}

下面是动态代理:
   因为我们发现这个本来跟业务没有多大关系的安全性检查,要是全部类全部方法都要用上的话,那不是要写死人。所以jdk为我们提供了动态代理这个方法,就是为了完成很多方法都需要拥有相同的功能的时候,我们也可以把这种东西叫做模块化。具体步骤是这样的:

接口和实现类没有任何变化。关键是代理类,我们把他抽取成一个对象,这个对象拥有一些公共的方法,也就是把共有的方法模块化了:
package com.lovo.json.module;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SelfHandler implements InvocationHandler {

 //拥用代理目标对象的引用
 private Object targetObj;
 
 //用对外提供一个返回被代理对象的方法 你才晓得你代理的是哪个
 public Object newProxy(Object targetObj){
  this.targetObj = targetObj;
  return Proxy.newProxyInstance(this.targetObj.getClass().getClassLoader(),//得到类加载器
         this.targetObj.getClass().getInterfaces(), //得到该类

的接口
         this);//代理类
 }
 
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  this.salf();
  //因为有些方法有返回值而有些没有,所以跟个结果
  Object reslut = null;
  //方法不做任何判定的情况是默认加到所有方法,所以Spring用了正则表达式来区分哪些方法需要加,哪些不需要
  reslut = method.invoke(this.targetObj, args);
  return reslut;
 }
 
 private void salf(){
  System.out.println("---------salf-------");
 }
}
这样就完成了所有工作,下面来测试一下:
package com.lovo.json.client;

import com.lovo.json.bean.UserManager;
import com.lovo.json.bean.UserManagerImp;
import com.lovo.json.module.SelfHandler;

import junit.framework.TestCase;

public class TestClient extends TestCase{
 public void testProxy(){
  //首先必须产生一个代理类
  SelfHandler handler = new SelfHandler();
  UserManager userManager =  (UserManager)handler.newProxy(new UserManagerImp());
  userManager.add("ad", "asd");
 }
}
测试成功,所有方法都添加了安全性检查这个功能。
从上面的列子可以看出,当Spring实现AOP功能的时候,他还是利用了jdk里面的动态代理方式,下面我们再来看看Spring里面怎么实现AOP的,他有两种实现方法,一种是XML的,一种是注解的,我们通过XML的方式来和上面的动态代理做比较,这样会有更清晰的认识。
首先两个基础类还是没有变化,就是一个接口一个实现类。这里需要变化的只有一点,就是我们的handler也就是功能模块,对于Spring来说他是轻量级的框架,不需要继承他的什么东西,所以handler类就变成了这样:
package com.lovo.json.module;

public class SelfHandler {

 private void salf() {
  System.out.println("---------salf-------");
 }
}
然后我们只需要在xml做如下的配置就可以了

 <!-- 肯定要用到两个类的实例所以创建两个类 -->
 <bean id="userManager" class="com.lovo.json.bean.UserManagerImp" />

 <bean id="selfHandler" class="com.lovo.json.module.SelfHandler" />

 <!-- 然后需要用到aop中的配置 aop config -->
 <aop:config>
  <aop:aspect id="self" ref="selfHandler"><!-- 这里指的是切入点也就是我的handler -->
   <!-- 切入点是配出来的 expression_r表达式嘛-->
   <aop:pointcut id="allAddMethod" expression_r="execution(* *(..))"/>
   <!-- 这里是之前还是之后执行哪个方法,往哪个切入点开始切->
   <aop:before method="salf" pointcut-ref="allAddMethod"/>
  </aop:aspect>
 </aop:config>
</beans>
就总结到这里,上课胡老还讲了个其他的方法,好好温习一下,原理都差不多,over!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值