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

时间: 2024-10-11 17:16:53

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

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

一.概述. 上一篇博客讲述了用注解的形式实现AOP如今讲述第二种AOP实现的方式利用XML来实现AOP. 二.代码演示. 准备工作參照上一篇博客<菜鸟学习Spring--60s使用annotation实现简单AOP> 文件夹结构: 事实上比起上一篇博客中用annotation来实现AOP的方式我们仅仅要把SecurityHandler.java和配置文件applicationContext.xml更改为以下内容就能够了.以下我把这两个文件的代码写下来. SecurityHandler.java

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

一.概述. Spring与Hibernate的集成在企业应用中是很常用的做法通过Spring和Hibernate的结合能提高我们代码的灵活性和开发效率,下面我就一步一步的给大家讲述Spring如何和Hibernate集成的. 二.代码演示. 导入Hibernate的jar包 Hibernate-3.2/lib/*.jar Hibernate-3.2/hibernate3.jar 还有导入Spring的相关jar包 我用的数据库是MySql所以要导入MySql的驱动jar包: mysql-conn

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

一.概述 AOP的实现方法在上两篇博客中已经用了两种方法来实现现在的问题来了虽然我们利用AOP,那么客户端如何信息传递?利用JoinPoint接口来实现客户端给具体实现类的传递参数. 二.代码演示. 目录结构: SecurityHandler.java package com.tgb.spring; import org.aspectj.lang.JoinPoint; public class SecurityHandler{ private void checkSecurity(JoinPoi

细说Spring——AOP详解(动态代理实现AOP)

前言 嗯,我应该是有一段实现没有写过博客了,在写完了细说Spring——AOP详解(AOP概览)之后,我发现我不知道该怎么写AOP这一部分,所以就把写博客这件事给放下了,但是这件事情又不想就这么放弃,所以今天我仔细思考了一下,决定还是要克服困难,我仔细的想了一下怎么讲解AOP实现这一部分,然后我决定由浅入深的讲解动态代理,然后用动态代理实现一个简单的AOP,感觉这样能够让人对AOP的原理有一个比较深刻的认识,希望能帮到大家.而且最近学习又组建了ACM比赛的队伍,虽然已经要大三了,按理来说应该一心

Spring之AOP原理_动态代理

面向方面编程(Aspect Oriented Programming,简称AOP)是一种声明式编程(Declarative Programming).声明式编程是和命令式编程(Imperative Programming)相对的概念.我们平时使用的编程语言,比如C++.Java.Ruby.Python等,都属命令式编程.命令式编程的意思是,程序员需要一步步写清楚程序需要如何做什么(How to do What).声明式编程的意思是,程序员不需要一步步告诉程序如何做,只需要告诉程序在哪些地方做什么

Spring学习笔记-AOP前传之动态代理

假设有如下需求: 写一个计算器类,里面包含加减乘除四个方法.在每个方法开始前打印出该方法开始的消息,在每个方法结束前打印出该方法结束的消息和计算的结果. 普通方法,先写一个借口,然后在接口里实现四个方法.在每个方法里加上要打印的语句.实现代码如下. ArithmeticCalculator接口 package com.spring.aop.helloworld; public interface ArithmeticCalculator { int add(int i, int j); int 

spring如何管理mybatis(一) ----- 动态代理接口

问题来源 最近在集成spring和mybatis时遇到了很多问题,从网上查了也解决了,但是就是心里有点别扭,想看看到底怎么回事,所以跟了下源码,终于发现了其中的奥妙. 问题分析 首先我们来看看基本的配置. spring的配置: <!-- 数据库配置 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="

Spring总结七:AOP动态代理的实现

Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类. 首先我们来用代码简单演示jdk动态代理: 现在有一个商品的增删改查的操作 /** * 商品操作接口 */ public interface ProductService { public void add(); public void edit(); public void delte(); public void select(); } /** * 实现类 */ public class Pr

Spring框架5:事务和动态代理

事务 我们在service中加一个转账的功能 public void transfer(String sourceName, String targetName, Float money) { Account source = accountDao.findAccountByName(sourceName); Account target = accountDao.findAccountByName(targetName); source.setMoney(source.getMoney() -