静态代理 和 JDK动态代理

接口:UserManager.java

  
    
1 package com.springdemo.manager;
2
3   public interface UserManager {
4 public void add(String name,String password);
5 public void delete(String name);
6 public int count();
7 }  

类:UserManagerImpl.java

代码
   
     
1 package com.springdemo.manager;
2
3   public class UserManagerImpl implements UserManager {
4
5 public void add(String name, String password) {
6 System.out.println( " do add user ... " );
7 }
8
9 public void delete(String name) {
10 System.out.println( " do delete user ... " );
11 }
12
13 public int count() {
14 return 10 ;
15 }
16 }

 

问题:现要求在调用UserManager的每个方法时,都要检查操作员权限,但不能改变UserManagerImpl的代码。

 

静态代理实现:

静态代理类:UserManagerProxy.java

代码
   
     
package com.springdemo.manager;

public class UserManagerProxy implements UserManager {

private UserManagerImpl impl;

public UserManagerProxy() {
this .impl = new UserManagerImpl();
}

public void add(String name, String password) {
checkPower();
this .impl.add(name, password);
}

public void delete(String name) {
checkPower();
this .delete(name);
}

public int count() {
checkPower();
return this .impl.count();
}

private void checkPower() {
System.out.println(
" check manager power .... " );
}

}

这就是静态代理的思想。

测试代码:

代码
   
     
1 package com.springdemo.client;
2
3   import com.springdemo.manager.UserManager;
4   import com.springdemo.manager.UserManagerProxy;
5
6
7   public class Client {
8 public static void main(String[] args) {
9 UserManager userManager = new UserManagerProxy();
10 userManager.add( " name.. " , " pwd.. " );
11 }
12
13 }

 

 

静态代理存在一个问题,比如,当我们在被代理的类中增加了一个方法,代理类中也要增加相应方法。

为此,JDK中提供了动态代理接口。

 

Jdk动态代理:

我们只需要写一个自定义的调用处理器(实现接口java.lang.reflect.InvokationHandler),然后使用类java.lang.reflect.Proxy中的静态方法 newProxyInstance 来为需要被代理的类自动生成代理类(这个代理类是自动成得,不可见得),并把这个代理类当做原先的类使用即可。

 

调用处理器类:UserManagerHandler.java

代码
   
     
1 package com.springdemo.manager;
2
3   import java.lang.reflect.InvocationHandler;
4   import java.lang.reflect.Method;
5
6   public class UserManagerHandler implements InvocationHandler {
7
8 private Object target;
9
10 public UserManagerHandler(Object target){
11 this .target = target;
12 }
13
14 /**
15 * (自动生成的)代理类将自动用这个方法这执行我们调用的方法。所以我们可以在这里插入我们想执行的代码。
16 * 这个方法是代理类调用的,所以以下参数也是代理类传的。它们的分别是:
17 * @param proxy 调用的代理类(就是自动生成的代理类的实例)
18 * @param method 我们调用的方法
19 * @param args 我们调用方法时传的参数
20 */
21 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
22 try {
23 checkPower();
24
25 // 这里会执行我们调用的方法,如果被调用方法没有返回值(void申明),这里返回null
26   Object returnValue = method.invoke(target, args);
27 return returnValue;
28 } catch (Exception e){
29 throw e;
30 }
31 }
32
33 private void checkPower() {
34 System.out.println( " check manager power .... " );
35 }
36 }
37  

 

测试代码:

代码
   
     
1 package com.springdemo.client;
2
3   import java.lang.reflect.InvocationHandler;
4   import java.lang.reflect.Proxy;
5
6   import com.springdemo.manager.UserManager;
7   import com.springdemo.manager.UserManagerHandler;
8   import com.springdemo.manager.UserManagerImpl;
9
10
11   public class Client {
12 public static void main(String[] args) {
13 // UserManager userManager = new UserManagerProxy();
14 // userManager.add("name..", "pwd..");
15  
16 UserManager userManager = new UserManagerImpl();
17 ClassLoader loader = Client. class .getClassLoader();
18 Class <?> [] interfaces = {UserManager. class };
19 InvocationHandler h = new UserManagerHandler(userManager);
20 userManager = (UserManager)Proxy.newProxyInstance(loader, interfaces, h);
21 userManager.add( " name.. " , " pwd.. " );
22 userManager.count();
23 }
24
25 }

 

优化UserManagerHandler.java

代码
   
     
1 package com.springdemo.manager;
2
3   import java.lang.reflect.InvocationHandler;
4   import java.lang.reflect.Method;
5   import java.lang.reflect.Proxy;
6
7   public class UserManagerHandler implements InvocationHandler {
8
9 private Object target;
10
11
12 // public UserManagerHandler(Object target){
13 // this.target = target;
14 // }
15  
16 public Object newProxy(Object target){
17 this .target = target;
18 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this );
19 }
20
21 /**
22 * (自动生成的)代理类将自动用这个方法这执行我们调用的方法。所以我们可以在这里插入我们想执行的代码。
23 * 这个方法是代理类调用的,所以以下参数也是代理类传的。它们的分别是:
24 * @param proxy 调用的代理类(就是自动生成的代理类的实例)
25 * @param method 我们调用的方法
26 * @param args 我们调用方法时传的参数
27 */
28 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
29 try {
30 checkPower();
31
32 // 这里会执行我们调用的方法,如果被调用方法没有返回值(void申明),这里返回null
33   Object returnValue = method.invoke(target, args);
34 return returnValue;
35 } catch (Exception e){
36 throw e;
37 }
38 }
39
40 private void checkPower() {
41 System.out.println( " check manager power .... " );
42 }
43 }
44  

测试代码:

代码
   
     
1 package com.springdemo.client;
2
3   import com.springdemo.manager.UserManager;
4   import com.springdemo.manager.UserManagerHandler;
5   import com.springdemo.manager.UserManagerImpl;
6
7
8   public class Client {
9 public static void main(String[] args) {
10 // UserManager userManager = new UserManagerProxy();
11 // userManager.add("name..", "pwd..");
12  
13 UserManager userManager = new UserManagerImpl();
14 UserManagerHandler h = new UserManagerHandler();
15 userManager = (UserManager)h.newProxy(userManager);
16 userManager.add( " name.. " , " pwd.. " );
17 userManager.count();
18 }
19
20 }
21  

 

以这个动态代理的例子,说明一下Spring中AOP术语:

1.切面(Aspect),对应UserMenagerHandler这个类。

2.  连接点(JoinPoint),切面应用在某个方法上,这个方法就是连接点,如:UserManagerImpl类中的add()方法。

3. 处理逻辑(Advice),对应UserMenagerHandler中的 checkPower() 方法。

 (处理逻辑(Advice)通常有:Before(前置通知),After(后置通知),Around(环绕通知),Throw(异常通知))

4. 切点(PointCut),连接点的集合,审明处理逻辑在哪些方法上应用。

5.  目标对象,对应UserManagerImpl的实例。

6.  把Aspect应用到Manager的方法上,叫置入。

你可能感兴趣的:(JDK动态代理)