关于java 动态代理详细讲解

        近来比较闲,又看来下java代理的api 感觉之前对他的理解不是很深  现在又重新看了一遍 记录下自己的感受吧!

   那么我们认识下 什么是代理呢? 小弟语文学的不好 ,就用如下代码来说吧! 

      我们模仿 登录 注册 业务案列 来讲解   

/**
* 定义登录接口
**/
interface login{
  boolean login(String username,String password);	
  boolean creadUser(String username,String password);	
}
/**
* 实现登录接口
**/

class loginImpl implements login {

	@Override
	public boolean login(String username, String password) {
		System.out.println("出来核心登录逻辑"+ "帐号是 : "+username +"     密码是:    "+ password);
		return true;
	}

	@Override
	public boolean creadUser(String username, String password) {
		System.out.println("我只是注册 不需要家其他业务处理" +"    注册的帐号:  "+username +" 注册时的密码   :   "+password);
		return true;
	}
}
   
	
         /**
	 * 
	 *  登录成功也需要添加业务逻辑
  	 * @author jade
	 *
	 */
	class Pox extends loginImpl{
		
		@Override
		public boolean login(String username, String password) {
		        System.out.println("登录前业务添加逻辑 pox 1 静态代理");
		      boolean is=  super.login(username, password);
		        System.out.println("登录后业务添加逻辑 pox 1 静态代理");
			return is;
		}
		
	} 
	
	/**  ----------------------------- 讲解代理 开始  end        ***/	

  如上 Pox 的存在原因是因为需求的变动,又不想去改动原来的业务 所以他就出现了!   Pox 就是传说中的代理  

上面代理的缺点显易见 - 一个代理只能为一个接口服务  为了解决这个问题  java 就出来了动态代理  

那就何为动态代理 ? 说白了就是 一个接口《java.lang.reflect.invocationHandler》 一个类《java.lang.reflect 类 Proxy》  如何不是和了解的 话几分钟看下api  好那我们把上面的静态代理修改成jdk 动态代理




	class Pox2 implements InvocationHandler{
		private Pox p;
		Pox2(){};
               Pox2(Object o){
			this.p=o;
		}
		

//		
//		Object getPox(Object o){
//			
//			this.p = o;  
//	        //取得代理对象  
//	        return Proxy.newProxyInstance(o.getClass().getClassLoader(),  
//	        		o.getClass().getInterfaces(), this);            //  得到代理对象有很多方式 可以参阅 api  我这里写了两种一个是通过构造函数得到 一个是通过调用getPox :查了网上论坛大部分用//的是getPox  
//			
//		}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		   Object r=null;
		     //    如下演示 业务处理
		   if(method.getName().equals("login")){
			   System.out.println("登录前业务添加逻辑 pox 2 动态代理");
			   r= method.invoke(p, args);
			  System.out.println("登录后业务添加逻辑 pox 2 动态代理");
			   
		   }else{
			   r= method.invoke(p, args);
			   
		   }
		
		return r;
	}
		
		
	}



 如上就实现了 jdk 动态的代理拉 简单吧   来个测试类吧

public class StadyPox {
	
	public static void main(String[] args) {
	   
		InvocationHandler proxy2 = new Pox2(new loginImpl());  
                 login login3=(login) Proxy.newProxyInstance(loginImpl.class.getClassLoader(),loginImpl.class.getInterfaces() , proxy2);
		 login3.login("c", "d");
		 login3.creadUser("e", "f");
</pre><pre name="code" class="java">//----------------------  如上是通过构造函数 实现的 如下是直接通过getPox()得到
<pre name="code" class="java" style="color: rgb(146, 147, 175); font-size: 11px;">//		   login login2 = (login) proxy2.getPox(new loginImpl());  
//		   login2.login("a", "b"); 
 //                <span style="font-family: Times;">login2</span><span style="font-family: Times;">.creadUser("e", "f");</span>
}}

 

 关于动态代理的讲解就到这里了  看下

Proxy.newProxyInstance(loginImpl.class.getClassLoader(),loginImpl.class.getInterfaces() , proxy2) 你看到了什么呢? loginImpl.class.getInterfaces() ?? 这个的意思就是 他必须有实现接口 那就是jdk 动态代理 必须要有接口 才能使用 

那如果在没有接口的情况下 那我们如何实现动态代理 ??  cglib  代理

      cglib 代理 其原理是 继承实现类 在继承的原则下面覆盖父类方法体  也就是  final 类不能代理 因为 他不能被继承

再次模拟 登录业务 讲解 cglib   

class loginImpl2 {

	
	public boolean login(String username, String password) {
		System.out.println("出来核心登录逻辑"+ "帐号是 : "+username +"     密码是:    "+ password);
		return true;
	}

	
	public boolean creadUser(String username, String password) {
		System.out.println("我只是注册 不需要家其他业务处理" +"    注册的帐号:  "+username +" 注册时的密码   :   "+password);
		return true;
	}
}

由上面代码可以看出 , 没有实现接口  。如下写cglib 代理类  写法方式和jdk 代理类似


class cglib  implements MethodInterceptor{
		
		 private Object pox;  
		  
		   
		    public Object getPox(Object o) {  
		        pox = o;  
		        Enhancer enhancer = new Enhancer();  
		        enhancer.setSuperclass(this.pox.getClass());  
		        // 回调方法  
		        enhancer.setCallback(this);  
		        // 创建代理对象  
		        return enhancer.create();  
		    }  
		  
		    @Override  
		    // 回调方法  
		    public Object intercept(Object obj, Method method, Object[] args,  
		            MethodProxy proxy) throws Throwable {  
		        System.out.println("事物开始");  
		        proxy.invokeSuper(obj, args);  
		        System.out.println("事物结束");  
		        
		      
		        return null;  
		  
		  
		    }  
		  
		
		
	}
以上就是cglib动态代理      来个测试下吧!
class TestCglib {
	public static void main(String[] args) {
		loginImpl2 login4 = new loginImpl2();
		cglib cglibProxy = new cglib();
		loginImpl2 hw = (loginImpl2) cglibProxy.getInstance(login4);

		System.out.println(hw.getClass().getSuperclass());

		System.out.println("ssksksk      " + login4.getClass().getSuperclass());

		hw.login("aa", "bb");
	}
}


得出的结果:

class jada.java.lang.reflect.loginImpl2

ssksksk      class java.lang.Object

事物开始

出来核心登录逻辑帐号是 : aa     密码是:    bb

事物结束



class jada.java.lang.reflect.loginImpl2   有此可以得出  --他说继承了 loginImpl2    

开始出来个疑问 直接打印代理类

System.out.println(hw)  结果是null  并且它执行了一次 <span style="color: rgb(146, 147, 175);font-size:18px;"></span><pre name="code" class="java"> public Object intercept(Object obj, Method method, Object[] args,  
		            MethodProxy proxy) throws Throwable        

 



同样的方式 我打印了 jdk动态实现的

public class StadyPox {

	public static void main(String[] args) {

		loginImpl a = new loginImpl();
		InvocationHandler proxy2 = new Pox2(a);
		login login3 = (login) Proxy.newProxyInstance(
				loginImpl.class.getClassLoader(),
				loginImpl.class.getInterfaces(), proxy2);
		System.out.println(a);
		System.out.println(login3);
		login3.login("c", "d");
		// login login2 = (login) new Pox2().bingTage(new loginImpl());
		// login2.login("a", "b");

	}

}
 出来的结果是:

jada.java.lang.reflect.loginImpl@2e8f4fb3

jada.java.lang.reflect.loginImpl@2e8f4fb3

登录前业务添加逻辑 pox 2 动态代理

出来核心登录逻辑帐号是 : c     密码是:    d

登录后业务添加逻辑 pox 2 动态代理











      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值