您的位置:首页 > 编程语言 > Java开发

spring AOP 静态代理和动态代理

2017-06-22 16:28 399 查看
原文:点击打开链接

spring AOP:称为spring的面向切面编程。

既然是切面,自然是要加入一些其他的与逻辑无关的功能,如身份校验,日志打印等。但是,如果代码中加入了这些功能,有新需求时又需要全部更改,这无疑很麻烦,于是就有了代理类的出现:静态代理,动态代理。

1.UserService

public interface UserService {

  public void addUser();

  public void deleteUser();

}

 

2.UserServiceImpl

public class UserServiceImpl implements UserService {

 public void addUser() {

      System.out.println("add user");

 }

 public void deleteUser() {

  System.out.println("delete user");

 }

}

 

那么这个时候要在添加和删除之前添加开始打印的日志,并且完成时添加结束打印的日志。

先来看静态代理:

3.UserProxyImpl

public class UserProxyImpl implements UserService{

    private UserServiceImpl userServiceImpl;

 

    public UserProxyImpl(UserServiceImpl userServiceImpl){

     this.userServiceImpl = userServiceImpl;

    }

 @Override

 public void deleteUser() {

    System.out.println("begin delete user");

       userServiceImpl.deleteUser(); 

       System.out.println("end delete user");

 }

 @Override

 public void addUser() {

    System.out.println("begin add user");

    userServiceImpl.addUser(); 

    System.out.println("end add user");

 }

}

 

 

4.TestProxy

public class TestProxy {

    public static void main(String[] args) {

     UserProxyImpl userProxyImpl = new UserProxyImpl(new UserServiceImpl());

     userProxyImpl.addUser();

 }

}

这样即是使用静态代理,虽然打印日志时,不会改变userServiceImpl里面的内容,但是如果添加需求时,仍然要改变userProxyImpl里面的内容,如果方法有上百个,可知工作量是多么的大,太麻烦了。动态代理可以解决这个问题。

 

动态代理:动态代理常用的,主要有jdk的动态代理,cglib的动态代理

区别:jdk的动态代理一定是用于接口,但是cglib是用于类,有没有接口都实现。

先来看jdk的动态代理:

1.UserService接口

 同上

2.UserServiceImpl实现类

 同上

不再需要UserProxyImpl了,而是将打印日志的语句单独的抽象出来放到一个类中,该类实现InvocationHandler接口

3.addLog

public class addLog implements InvocationHandler{

  private Object taObject;  

      

 public Object createProcy(Object objectTarget){

  this.taObject=objectTarget;

  return Proxy.newProxyInstance(taObject.getClass().getClassLoader(),

                          taObject.getClass().getInterfaces(),

                          this);

 }

 public Object invoke(Object proxy, Method method, Object[] args)

   throws Throwable {

  beforeLog();

    Object object = method.invoke(taObject, args);

  afterLog();

  return object;

 }

 

 private void beforeLog(){

  System.out.println("begin ooperation");

 }

 private void afterLog(){

  System.out.println("after operation");

 }

}

 解释一下这个addLog类,该类有四个方法,分别为createProxy,invoke,beforeLog,afterLog,其中invoke方法为实现InvocationHander时重载的方法。

 

creteProxy方法:需要的参数为需要代理的类,Proxy.newProxyInstance将返回一个代理类,参数分别为:

  taObject.getClass().getClassLoader():得到被代理类的加载器

 taObject.getClass().getInterfaces():得到被代理类的所有接口

 this:将得到该InvocationHandler的子类

 

产生的代理类,最终将调用invoke方法中的method.invoke来执行真正的被代理类,不过开始和结束都有打印日志的方法,所以invoke方法里面有个Proxy参数,就是用来调用方法的代理类。

 

4.TestProxy

public class TestProxy {

    public static void main(String[] args) {

     CheckSecurity checkSecurity = new CheckSecurity();

     UserService userService = (UserService)checkSecurity.createProcy(new UserServiceImpl());

  userService.deleteUser();

 }

}

可以看到userService为jdk的代理类

 

如果不实现userService接口,UserServiceImpl中自己拥有addUser,deleteUser方法,那么同样的addLog类,生成的代理类将为cglib代理类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: