Spring(十)通过动态代理(JDK的Proxy)和cglib实现AOP技术

目标对象的所有接口方法

package test.spring.service;

public interface PersonService {

	public String getPersonName(Integer id);

	public void save(String name);

}

目标对象

package test.spring.service.impl;

import test.spring.service.PersonService;

//代理对象实现目标对象所有接口
public class PersonServiceBean implements PersonService {

	private String user = null;

	public PersonServiceBean() {

	}

	public PersonServiceBean(String user) {
		super();
		this.user = user;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	@Override
	public String getPersonName(Integer id) {
		// TODO Auto-generated method stub
		return "getPersonName";
	}

	@Override
	public void save(String name) {
		// TODO Auto-generated method stub
		System.out.println("save()->>" + name);
	}

}

代理对象,拦截所有业务方法,根据user是否为null判断用户是否有权限,有权限就允许执行业务方法,无权限就不执行。

package test.spring.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import test.spring.service.impl.PersonServiceBean;

public class ProxyFactory implements InvocationHandler {

	private Object proxyObject;

	// 创建代理对象实例
	public Object createProxyIntance(Object proxyObject) {
		this.proxyObject = proxyObject;
		/*
		 * 第一个参数:类装载器
		 * 第二个参数:取得目标对象的接口,Proxy会将这些接口全部实现
		 * 第三个参数:一个回调函数,确定实现哪个类的接口
		 */
		return Proxy.newProxyInstance(this.proxyObject.getClass()
				.getClassLoader(), this.proxyObject.getClass().getInterfaces(),
				this);
	}

	/*
	 * 第一个参数:代理对象
	 * 第二个参数:被拦截到的方法
	 * 第三个参数:方法的输入参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		PersonServiceBean personServiceBean = (PersonServiceBean) this.proxyObject;
		Object target = null;
		// user不为空说明有权限
		if (personServiceBean.getUser() != null) {
			// 把对代理对象方法的调用委派给目标对象
			target = method.invoke(proxyObject, args);
		}
		return target;
	}
}

权限测试

package test.spring.junit;

import static org.junit.Assert.*;

import org.junit.Test;

import test.spring.aop.ProxyFactory;
import test.spring.service.PersonService;
import test.spring.service.impl.PersonServiceBean;

public class AOPTest {

	@Test
	public void test() {
		ProxyFactory pFactory = new ProxyFactory();

		// PersonService pService=(PersonService)
		// pFactory.createProxyIntance(new PersonServiceBean("kkk"));

		// 改为默认函数pService.save("ppp")就执行不了,因为前面的user=null,相当于没有权限执行
		PersonService pService = (PersonService) pFactory
				.createProxyIntance(new PersonServiceBean());
		pService.save("ppp");
	}

}

以上适用于目标对象实现了接口的情况,如果目标对象没有接口,就会选择用Cglib

首先导入cglib-nodep-2.1_3.jar

package test.spring.service.impl;

//代理对象实现目标对象所有接口
public class PersonServiceBean2 {

	private String user = null;

	public PersonServiceBean2() {

	}

	public PersonServiceBean2(String user) {
		super();
		this.user = user;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public void save(String name) {
		// TODO Auto-generated method stub
		System.out.println("save()->>" + name);
	}

}
package test.spring.aop;

import java.lang.reflect.Method;

import test.spring.service.impl.PersonServiceBean2;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

//目标对象没有接口
public class CglibProxyFactory implements MethodInterceptor {
	private Object proxyObject;

	// 创建代理对象实例
	public Object createProxyIntance(Object proxyObject) {
		this.proxyObject = proxyObject;

		Enhancer enhancer = new Enhancer();
		/*
		 * 需设置父类,即目标类。创建的对象继承目标类,对目标类中
		 * 所有非final的所有方法进行覆盖,然后在覆盖的代码里面
		 * 添加一些自身的代码
		 */
		enhancer.setSuperclass(this.proxyObject.getClass());
		enhancer.setCallback((Callback) this);
		return enhancer.create();

	}

	/*
	 * 第一个参数:代理对象本身
	 * 第二个参数:被拦截到的方法
	 * 第三个参数:方法的参数
	 * 第四个参数:方法的代理对象
	 */
	// 当代理对象的业务方法被回调的时候会调用这个方法
	@Override
	public Object intercept(Object proxy, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		PersonServiceBean2 personServiceBean = (PersonServiceBean2) this.proxyObject;
		Object target = null;
		// user不为空说明有权限
		if (personServiceBean.getUser() != null) {
			// 把对方法的调用委派给目标对象
			target = methodProxy.invoke(proxyObject, args);
		}
		return target;
	}
}
package test.spring.junit;

import static org.junit.Assert.*;

import org.junit.Test;

import test.spring.aop.CglibProxyFactory;
import test.spring.aop.ProxyFactory;
import test.spring.service.PersonService;
import test.spring.service.impl.PersonServiceBean;
import test.spring.service.impl.PersonServiceBean2;

public class AOPTest2 {

	@Test
	public void test() {
		CglibProxyFactory pFactory = new CglibProxyFactory();

		// 此时PersonServiceBean没有接口
		PersonServiceBean2 pService = (PersonServiceBean2) pFactory
				.createProxyIntance(new PersonServiceBean2("kkk"));

		pService.save("ppp");
	}

}

版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载,请注明出处:http://blog.csdn.net/lindonglian

时间: 2024-10-12 17:52:42

Spring(十)通过动态代理(JDK的Proxy)和cglib实现AOP技术的相关文章

Java动态代理——JDK和CGlib(简单易懂)

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6542259.html 一:代理模式(静态代理) 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由 业务实现类.业务代理类 两部分组成.业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截.过滤.预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法,还可以规定调用后的操作.我们在需要调用业务时,不是直接通过业

探索Mybatis之JDK动态代理:探究Proxy.newProxyInstance()生成的代理类解析

Mybatis的Mapper接口UserMapper 1 package com.safin.Mapper; 2 3 import com.safin.Pojo.User; 4 5 import java.util.List; 6 7 public interface UserMapper { 8 int insertUser(User user); 9 User getUser(Long id); 10 List<User> findUser(String userName); 11 } 我

spring中使用动态代理(AOP)

spring是整合了BGLIB和JDK两种动态代理 示例:使用CGLIB代理 public class MyCar { private String color = "blue"; public void run() { System.out.println("我的汽车跑起来了" + color); } } 测试 public class SpringProxy { public static void main(String[] args) { //将代理类的cl

springmvc 动态代理 JDK实现与模拟JDK纯手写实现。

首先明白 动态代理和静态代理的区别: 静态代理:①持有被代理类的引用  ② 代理类一开始就被加载到内存中了(非常重要) 动态代理:JDK中的动态代理中的代理类是动态生成的.并且生成的动态代理类为$Proxy0 静态代理实例1.创建一个接口: package proxy; public interface People { public void zhaoduixiang()throws Throwable; } 2.创建一个实现类,张三,张三能够吃饭,张三可以找对象 package proxy;

spring 系列6 动态代理

在业务中使用动态代理,一般是为了给需要实现的方法添加预处理或者添加后续操作,但是不干预实现类的正常业务,把一些基本业务和主要的业务逻辑分离. 基于JDK的动态代理只需知道两个东西:1.InvocationHandler(接口).2.Proxy(类) 一.创建一个接口 public interface Subject{ void hello(String param); } 二.实现接口 public class SubjectImpl implements Subject{ public voi

java 动态代理深度学习(Proxy,InvocationHandler),含$Proxy0源码

java 动态代理深度学习, 一.相关类及其方法: java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxyInstance()返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序(详见api文档) java.lang.reflect.InvocationHandler,InvocationHandler 是代理实例的调用处理程序 实现的接口. invoke()在代理实例上处理方法调用并返回结果.在与方法关联的代理

03、动态代理--JDK动态代理和CGLib动态代理的组合实例

package com.offer.note.Java基础.动态代理.CGLib引入增强; public interface Browser { void visitInternet(); } package com.offer.note.Java基础.动态代理.CGLib引入增强; /** * 目标类:被代理类 * * @author: xueguanfeng * @date: 2018-05-15 09:57 */ public class ChromeBrowser implements

二十二 动态代理&amp;解决网站的字符集编码问题

设计模式: 软件开发过程中,遇到相似问题,将问题的解决方式抽取模型(套路) 单例,工厂,装饰者,适配器,动态代理 谷歌汽车场景: 谷歌汽车场景Car 设计了汽车开发阅读 Interface Icar{  start  run  stop} final class GoogleCar implments ICar(){} 希望将谷歌Car接入到生态圈 装饰者设计模式 场景:二次开发的时候,无法获取源码GoogleCar,无法使用继承的情况下,要对已经存在的对象进行增强 前提:可以获取到被装饰的对象

Java使用动态代理实现AOP

参考资料: http://www.importnew.com/15420.htmlhttp://www.cnblogs.com/techyc/p/3455950.html Spring是借助了动态代理(JDK dynamic proxy)和CGlib两种技术实现AOP的,本文将学习前人的例子使用动态代理模拟AOP的特性. 1. 环境 Java: jdk1.8.0_144 2. 学习动态代理Proxy.newProxyInstance()方法 它的三个参数如下 参数名 类型 说明 loader C