菜鸟学习Spring——60s让你学会动态代理原理
最后更新于:2022-04-01 09:34:02
## 一、为什么要使用动态代理
当一个对象或多个对象实现了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://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-22_56caddfbd0dce.jpg)
## 三、总结。
动态代理的利用给我们编码带来了很大的便利,解决了动态为对象提供服务的方案。动态代理+IoC容器的结合让我们对系统提供服务更加的方便了这样我们也就实现了开闭原则。这样也就能实现了对象想要的时候就有不用的时候就撤出全心全意为开发者服务。