一、为什么要使用动态代理

        当一个对象或多个对象实现了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容器的结合让我们对系统提供服务更加的方便了这样我们也就实现了开闭原则。这样也就能实现了对象想要的时候就有不用的时候就撤出全心全意为开发者服务。

菜鸟学习Spring——60s让你学会动态代理原理的更多相关文章

  1. 菜鸟学习Spring——60s配置XML方法实现简单AOP

    一.概述. 上一篇博客讲述了用注解的形式实现AOP现在讲述另外一种AOP实现的方式利用XML来实现AOP. 二.代码演示. 准备工作参照上一篇博客<菜鸟学习Spring--60s使用annota ...

  2. 菜鸟学习Spring——60s使用annotation实现简单AOP

    一.概述. AOP大家都知道切面编程,在Spring中annotation可以实现简单的AOP列子.下面还未大家介绍几个概念: Aspect 对横切性关注点的模块化. Advice 对横切性关注点的具 ...

  3. 菜鸟学习Spring——60s学会Spring与Hibernate的集成

    一.概述. Spring与Hibernate的集成在企业应用中是很常用的做法通过Spring和Hibernate的结合能提高我们代码的灵活性和开发效率,下面我就一步一步的给大家讲述Spring如何和H ...

  4. 菜鸟学习Spring——60s利用JoinPoint获取参数的值和方法名称

    一.概述 AOP的实现方法在上两篇博客中已经用了两种方法来实现现在的问题来了虽然我们利用AOP,那么客户端如何信息传递?利用JoinPoint接口来实现客户端给具体实现类的传递参数. 二.代码演示. ...

  5. 菜鸟学习Spring——60s利用JoinPoint获取參数的值和方法名称

    一.概述 AOP的实现方法在上两篇博客中已经用了两种方法来实现如今的问题来了尽管我们利用AOP,那么client怎样信息传递?利用JoinPoint接口来实现client给详细实现类的传递參数. 二. ...

  6. Spring AOP动态代理原理与实现方式

    AOP:面向切面.面向方面.面向接口是一种横切技术横切技术运用:1.事务管理: (1)数据库事务:(2)编程事务(3)声明事物:Spring AOP-->声明事物   2.日志处理:3.安全验证 ...

  7. Spring @Trasactionl 失效, JDK,CGLIB动态代理

    @Transaction:  http://blog.csdn.net/bao19901210/article/details/41724355 Spring上下文:  http://blog.csd ...

  8. 动态代理 原理简析(java. 动态编译,动态代理)

    动态代理: 1.动态编译 JavaCompiler.CompilationTask 动态编译想理解自己查API文档 2.反射被代理类 主要使用Method.invoke(Object o,Object ...

  9. 设计模式 - 动态代理原理及模仿JDK Proxy 写一个属于自己的动态代理

    本篇文章代码内容较多,讲的可能会有些粗糙,大家可以选择性阅读. 本篇文章的目的是简单的分析动态代理的原理及模仿JDK Proxy手写一个动态代理以及对几种代理做一个总结. 对于代理模式的介绍和讲解,网 ...

随机推荐

  1. [ CodeVS冲杯之路 ] P1368

    不充钱,你怎么AC? 题目:http://codevs.cn/problem/1368/ 嗯……泡泡堂,很劲啊,其实就是个盗版的田忌赛马 http://www.cnblogs.com/hyfer/p/ ...

  2. 网易音乐API

    本次分析的是网易音乐API 歌曲搜索API:http://music.163.com/api/search/get/web?csrf_token= 需要用POST来获取 参数: Referer=htt ...

  3. Android开发-API指南-创建 Content Provider

    Creating a Content Provider 英文原文:http://developer.android.com/guide/topics/providers/content-provide ...

  4. JS(AS)中的原子操作

    原子操作这是Java多线程编程的老生常谈了.所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程). 当然 ...

  5. opecv轮廓匹配,可以用于去噪

    一个跟轮廓相关的最常用到的功能是匹配两个轮廓.如果有两个轮廓,如何比较它们;或者如何比较一个轮廓和另一个抽象模板. 矩 比较两个轮廓最简洁的方式是比较他们的轮廓矩.这里先简短介绍一个矩的含义.简单的说 ...

  6. oracle 空表无法导出

    1.执行该语句   select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0;  ...

  7. 多线程(二)NSThread

    一.NSThread优缺点      优点:NSThread是最轻量级的      缺点:需要自己管理线程的生命周期,线程同步.线程同步对数据的加锁会有一定的系统开销   二.NSThread的使用 ...

  8. 实时显示GetLastError值

    在Watch窗口中输入$err,hr 自动显示上个函数返回值

  9. sql server安装程序无法验证服务账户是什么原因

    为了帮助网友解决“sql server安装程序无法验证服务”相关的问题,中国学网通过互联网对“sql server安装程序无法验证服务”相关的解决方案进行了整理,用户详细问题包括:能是尚未向所有要安装 ...

  10. SVN 外部引用(svn:externals)处理相似系统的公用代码

    一.创建外部引用 我们常常遇到这样一个场景,我们有两个系统,两个系统用的是同一套框架.如果我们用两套程序 去做,当我们修改这个公共的框架的时候,另外一个还是旧版本的,很容易造成混乱. SVN的外部用就 ...