静态代理 和 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的方法上,叫置入。

posted on 2010-12-24 11:14  迎-客-松  阅读(314)  评论(0编辑  收藏  举报

导航