(9) 使用JDK中的Proxy技术实现AOP功能 以及 CGLIB生成代理

本文详细介绍了如何使用Java平台提供的JDK Proxy技术和CGLIB库实现面向切面编程(AOP)。通过实例展示了如何为类方法添加前置、后置等通知逻辑,确保在执行业务方法前后执行特定的逻辑操作,从而提高代码的复用性和可维护性。

第一种:使用JDK中的Proxy技术实现AOP功能


public class JDKProxy implements InvocationHandler {

    private Object targetObject;//代理的目标对象
    public Object createProxyInstance(Object targetObject){
        this.targetObject = targetObject;
/*
* 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器
* 第二个参数设置代理类实现的接口
* 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法
*/
        return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
                this.targetObject.getClass().getInterfaces(), this);
    }
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        return method.invoke(this.targetObject, args);//把方法调用委派给目标对象
    }
}

当目标类实现了接口,我们可以使用jdk的Proxy来生成代理对象。


package cn.itm.service;

public interface PersonService {

	public void save(String name);
	
	public void update(String name,Integer personid);
	
	public String getPersonName(Integer personid);
}

package cn.itm.service.impl;

import cn.itm.service.PersonService;

/**
 * 对这里面的所有方法 实施拦截,拦截到这个方式之后,我们判断,用户是否为 null,如果为null,就没有权限去调用这里面的方法。
 * @author Administrator
 *
 */
public class PersonServiceBean implements PersonService {
	
	
	private String user = null;
	
	public String getUser() {
		return user;
	}

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

	@Override
	public String getPersonName(Integer personid) {
		System.out.println("我是  getPersonName()方法 ");
		return "xxx";
	}

	@Override
	public void save(String name) {
		System.out.println("我是 save() 方法");
	}

	@Override
	public void update(String name, Integer personid) {
		System.out.println("我是 update() 方法");
	}

}

package cn.itm.aop;

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

import cn.itm.service.impl.PersonServiceBean;

public class JDKProxyFactory implements InvocationHandler{

	private Object targetObject;
	
	/**
	 * 调用对象 会 被this 拦截到。拦截到后,他会执行invoke() 方法    也就是说:客户端调用代理对象业务方法的时候,代理对象就会执行 InvocationHandler 找   invoke()方法
	 * 
	 * invoke方法就会   把 method的调用 委派给目标对象。
	 * 
	 * @param targetObject
	 * @return
	 */
	public Object createProxyInstance(Object targetObject){
		this.targetObject = targetObject;
		return Proxy.newProxyInstance(
				this.targetObject.getClass().getClassLoader(), 
				this.targetObject.getClass().getInterfaces(), 
				this
		);	
	}

	/**
	 * 
	 * @param proxy
	 * @param method : 代表被拦截到的方法,
	 * @param args   : 代表方法的输入参数。
	 * @return
	 * @throws Throwable
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		PersonServiceBean bean = (PersonServiceBean)this.targetObject;
		Object result = null;
		if(bean.getUser() != null){ // 代表如果有权限。
			// 委派给目标对象。
			result = method.invoke(targetObject, args);
		}
		
		return result;
	}
}

package junit.test;


import org.junit.BeforeClass;
import org.junit.Test;

import cn.itm.aop.JDKProxyFactory;
import cn.itm.service.PersonService;
import cn.itm.service.impl.PersonServiceBean;

public class AOPTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}
	
	@Test public void proxyTest(){
		JDKProxyFactory factory = new JDKProxyFactory();
		// 注意要使用接口 来饮用代理对象。
		PersonService personService = (PersonService)factory.createProxyInstance(new PersonServiceBean("XXX"));
		personService.save("999");
	}

}

ok,成功。


第二种:使用cglib


public class CGLIBProxy implements MethodInterceptor {
    private Object targetObject;//代理的目标对象   

    public Object createProxyInstance(Object targetObject){
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();//该类用于生成代理对象
        enhancer.setSuperclass(this.targetObject.getClass());//设置父类
        enhancer.setCallback(this);//设置回调用对象为本身

        return enhancer.create();
    }
    public Object    intercept(Object proxy, Method method, Object[] args,
            MethodProxy methodProxy) throws Throwable {
            return methodProxy.invoke(this.targetObject, args);
    }
}
CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。


代码示例:


不用实现接口

package cn.itm.service.impl;


/**
 * 对这里面的所有方法 实施拦截,拦截到这个方式之后,我们判断,用户是否为 null,如果为null,就没有权限去调用这里面的方法。
 * @author Administrator
 *
 */
public class PersonServiceBean{
	
	
	private String user = null;
	
	public String getUser() {
		return user;
	}

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

	public String getPersonName(Integer personid) {
		System.out.println("我是  getPersonName()方法 ");
		return "xxx";
	}

	public void save(String name) {
		System.out.println("我是 save() 方法");
	}

	public void update(String name, Integer personid) {
		System.out.println("我是 update() 方法");
	}

}

使用cglib实现:

package cn.itm.aop;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import cn.itm.service.impl.PersonServiceBean;

public class CGLIBProxyFactory implements MethodInterceptor{

private Object targetObject;
	
	public Object createProxyInstance(Object targetObject){
		this.targetObject = targetObject;
		Enhancer enhancer = new Enhancer();//该类用于生成代理对象
		enhancer.setSuperclass(this.targetObject.getClass());//设置父类
		
		enhancer.setCallback(this);//设置回调用对象为本身
		return enhancer.create();  // 创建代理对象。

	}
	
	public Object intercept(Object proxy, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		
		PersonServiceBean bean = (PersonServiceBean)this.targetObject;
		Object result = null;
		if(bean.getUser() != null){ // 代表如果有权限。
			// 委派给目标对象。
			result = methodProxy.invoke(targetObject, args);
		}
		
		return result;
	
	}

}

测试类

package junit.test;


import org.junit.BeforeClass;
import org.junit.Test;

import cn.itm.aop.CGLIBProxyFactory;
import cn.itm.service.impl.PersonServiceBean;

public class AOPTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}
	@Test public void cglibproxyTest(){
		CGLIBProxyFactory factory = new CGLIBProxyFactory();
		// 注意要使用接口 来饮用代理对象。
		PersonServiceBean personServiceBean = (PersonServiceBean)factory.createProxyInstance(new PersonServiceBean(/*"XXX"*/));
		personServiceBean.save("CGLIB----> 999");
	}

}




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值