zoukankan      html  css  js  c++  java
  • 菜鸟学习Spring——60s让你学会动态代理原理

    一、为什么要使用动态代理
            当一个对象或多个对象实现了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");
    		}
    	}
    


           三种方法的效果是一样的如图:


    三、总结。

            动态代理的利用给我们编码带来了很大的便利,解决了动态为对象提供服务的方案。动态代理+IoC容器的结合让我们对系统提供服务更加的方便了这样我们也就实现了开闭原则。这样也就能实现了对象想要的时候就有不用的时候就撤出全心全意为开发者服务。

  • 相关阅读:
    CentOS7上安装FTP服务
    CentOS7上安装Nginx、PHP、MySQL
    iOS-高性能编程之多线程
    Autoloader什么鬼
    PHP调用外部命令
    PHP使用Redis【重要】
    Windows系统上Redis的安装
    利用nginx与ffmpeg搭建流媒体服务器
    Ubuntu14.04上安装Composer
    find the most comfortable road(并差集,找差值最小的权值)
  • 原文地址:https://www.cnblogs.com/iplus/p/4490370.html
Copyright © 2011-2022 走看看