## 一、为什么要使用动态代理
当一个对象或多个对象实现了N中方法的时候,由于业务需求需要把这个对象和多个对象的N个方法加入一个共同的方法,比如把所有对象的所有方法加入事务这个时候有三种方法:
方法一:一个一个对象一个一个方法去加,很显然这个方法是一个比较笨的方法。
方法二:加一个静态代理对象将这个静态代理对象实现要加事务对象的接口。然后在静态代理对象里面每个方法里面加上事务。
方法三:使用动态代理对象,进行动态的加载事务。
使用动态代理是为了让对象实现了开闭原则,对扩展开放,而对修改关闭。Spring的AOP其实就是用了动态代理+IoC容器实现的
二、代码实现。> UserManger.java接口
~~~
package com.tgb.spring;
public interface UserManager {
public void addUser(String username,String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId,String username,String password);
}
~~~
方法一 常规的做法:
UserMangerImpl.Java
~~~
package com.tgb.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
checkSecurity();
System.out.println("UserManager.addUser");
}
public void delUser(int userId) {
checkSecurity();
System.out.println("UserManager.delUser");
}
public String findUserById(int userId) {
checkSecurity();
System.out.println("UserManager.findUserById");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
checkSecurity();
System.out.println("UserManager.modifyUser");
}
private void checkSecurity(){
System.out.println("checkSecurity");
}
}
~~~
Client.java
~~~
package com.tgb.spring;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
UserManager userManager=new UserManagerImpl();
userManager.addUser("11", "1231");
}
}
~~~
方法二 静态代理:
UserManagerImpl.java
~~~
package com.tgb.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
//checkSecurity();
System.out.println("UserManager.addUser");
}
public void delUser(int userId) {
//checkSecurity();
System.out.println("UserManager.delUser");
}
public String findUserById(int userId) {
//checkSecurity();
System.out.println("UserManager.findUserById");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
//checkSecurity();
System.out.println("UserManager.modifyUser");
}
// private void checkSecurity(){
// System.out.println("checkSecurity");
//
// }
}
~~~
UserManagerImplProxy.java
~~~
package com.tgb.spring;
public class UserManagerImplProxy implements UserManager {
private UserManager userManager;
public UserManagerImplProxy(UserManager userManager){
this.userManager=userManager;
}
public void addUser(String username, String password) {
// TODO Auto-generated method stub
checkSecurity();
userManager.addUser(username, password);
}
public void delUser(int userId) {
// TODO Auto-generated method stub
checkSecurity();
userManager.delUser(userId);
}
public String findUserById(int userId) {
// TODO Auto-generated method stub
checkSecurity();
return userManager.findUserById(userId);
}
public void modifyUser(int userId, String username, String password) {
// TODO Auto-generated method stub
checkSecurity();
userManager.modifyUser(userId, username, password);
}
private void checkSecurity(){
System.out.println("checkSecurity");
}
}
~~~
Client.java
~~~
package com.tgb.spring;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
UserManagerImpl uesrMangerImpl=new UserManagerImpl();
UserManager userManager=new UserManagerImplProxy(uesrMangerImpl);
userManager.addUser("11", "1231");
}
}
~~~
方法三:动态代理
UserManagerImpl.java与方法二的UserManagerImpl.java一样把UserManagerImplProxy.java删除
新添一个类:
SecurityHandler.java
~~~
package com.tgb.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SecurityHandler implements InvocationHandler {
private Object targetObject;
public Object createProxyInstance(Object targetObject){
this.targetObject=targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
checkSecurity();
//调用目标方法
Object ret=method.invoke(targetObject, args);
return ret;
}
private void checkSecurity(){
System.out.println("checkSecurity");
}
}
~~~
Client.java
~~~
package com.tgb.spring;
public class Client {
public static void main(String[] args) {
SecurityHandler handler=new SecurityHandler();
UserManager userManager=(UserManager)handler.createProxyInstance(new UserManagerImpl());
userManager.addUser("zha", "123");
}
}
~~~
三种方法的效果是一样的如图:
![](https://box.kancloud.cn/2016-02-22_56caddfbd0dce.jpg)
## 三、总结。
动态代理的利用给我们编码带来了很大的便利,解决了动态为对象提供服务的方案。动态代理+IoC容器的结合让我们对系统提供服务更加的方便了这样我们也就实现了开闭原则。这样也就能实现了对象想要的时候就有不用的时候就撤出全心全意为开发者服务。
- 前言
- 菜鸟学习Struts——配置Struts环境
- 菜鸟学习Struts——简易计算器
- 菜鸟学习Struts——bean标签库
- 菜鸟学习Struts——Scope属性
- 菜鸟学习Struts——国际化
- 菜鸟学习Struts——总结
- 菜鸟学习Hibernate——配置Hibernate环境
- 菜鸟学习Hibernate——持久层框架
- 菜鸟学习Hibernate——简单的一个例子
- 菜鸟学习Hibernate——简单的增、删、改、查操作
- 菜鸟学习Hibernate——一对多关系映射
- 菜鸟学习Hibernate——多对多关系映射
- 菜鸟学习Hibernate——缓存
- 菜鸟学习Spring——初识Spring
- 菜鸟学习Spring——第一个例子
- 菜鸟学习Spring——60s让你学会动态代理原理
- 菜鸟学习Spring——60s使用annotation实现简单AOP
- 菜鸟学习Spring——60s配置XML方法实现简单AOP
- 菜鸟学习Spring——60s利用JoinPoint获取参数的值和方法名称
- 菜鸟学习Spring——60s学会Spring与Hibernate的集成
- 菜鸟学习SSH——目录
- 菜鸟学习Spring——SpringMVC注解版前台向后台传值的两种方式
- 菜鸟学习Spring——SpringMVC注解版在服务器端获取Json字符串并解析
- 菜鸟学习Spring——SpringMVC注解版将URL中的参数转成实体
- 菜鸟学习Spring——SpringMVC注解版解析不同格式的JSON串
- 菜鸟学习Spring——SpringIoC容器基于三种配置的对比