转自:http://blog.csdn.net/xiaohai0504/article/details/6832990
介绍
代理模式
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种:
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
在JDK 1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例。 JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。
一)静态代理:
1.Count.java
- <span style="font-size:16px;">package net.battier.dao;
- /**
- * 定义一个账户接口
- *
- * @author Administrator
- *
- */
- public interface Count {
- // 查看账户方法
- public void queryCount();
- // 修改账户方法
- public void updateCount();
- } </span>
- package net.battier.dao.impl;
- import net.battier.dao.Count;
- /**
- * 委托类(包含业务逻辑)
- *
- * @author Administrator
- *
- */
- public class CountImpl implements Count {
- @Override
- public void queryCount() {
- System.out.println("查看账户方法...");
- }
- @Override
- public void updateCount() {
- System.out.println("修改账户方法...");
- }
- }
- package net.battier.dao.impl;
- import net.battier.dao.Count;
- /**
- * 这是一个代理类(增强CountImpl实现类)
- *
- * @author Administrator
- *
- */
- public class CountProxy implements Count {
- private CountImpl countImpl;
- /**
- * 覆盖默认构造器
- *
- * @param countImpl
- */
- public CountProxy(CountImpl countImpl) {
- this.countImpl = countImpl;
- }
- @Override
- public void queryCount() {
- System.out.println("事务处理之前");
- // 调用委托类的方法;
- countImpl.queryCount();
- System.out.println("事务处理之后");
- }
- @Override
- public void updateCount() {
- System.out.println("事务处理之前");
- // 调用委托类的方法;
- countImpl.updateCount();
- System.out.println("事务处理之后");
- }
- }
4.TestCount.java
- Java代码
- package net.battier.test;
- import net.battier.dao.impl.CountImpl;
- import net.battier.dao.impl.CountProxy;
- /**
- *测试Count类
- *
- * @author Administrator
- *
- */
- public class TestCount {
- public static void main(String[] args) {
- CountImpl countImpl = new CountImpl();
- CountProxy countProxy = new CountProxy(countImpl);
- countProxy.updateCount();
- countProxy.queryCount();
- }
- }
总结:什么是静态代理,比如我想吃黄牛娃凉皮,但是不方便自己去买,就让我的司机顺便帮我买(这里司机就是代理类,买黄牛娃凉皮放到一个类中作为被代理类)
类图如下:
代理类和委托类(被代理类)都实现接口,代理类 聚合 委托类 ,再代理类中使用委托类调用委托类的方法。
==========================================================================
二)动态代理
1.定义一个接口和实现类:
- <span style="font-weight: normal;"><span style="font-size:16px;">package com.tech.service;
- public interface PersonService {
- public String getPersonName(Integer personId);
- public void save(String name);
- public void update(Integer personId, String name);
- }
- package com.tech.service.impl;
- import com.tech.service.PersonService;
- public class PersonServiceBean implements PersonService {
- public String user = null;
- public PersonServiceBean(){};
- public PersonServiceBean(String user){
- this.user = user;
- }
- @Override
- public String getPersonName(Integer personId) {
- // TODO Auto-generated method stub
- System.out.println("这是find方法");
- return this.user;
- }
- @Override
- public void save(String name) {
- // TODO Auto-generated method stub
- System.out.println("这是save方法");
- }
- @Override
- public void update(Integer personId, String name) {
- // TODO Auto-generated method stub
- System.out.println("这是update方法");
- }
- public String getUser() {
- return user;
- }
- public void setUser(String user) {
- this.user = user;
- }
- }</span></span>
- package com.tech.jdkproxy;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import com.tech.service.impl.PersonServiceBean;
- /**
- *
- * 切面
- * @author ch
- *
- */
- public class JDKProxyFactory implements InvocationHandler{
- private Object proxyObject; //目标对象
- /**
- * 绑定委托对象并返回一个代理类
- * @param proxyObject
- * @return
- */
- public Object createProxyInstance(Object proxyObject) {
- this.proxyObject = proxyObject;
- //生成代理类的字节码加载器
- ClassLoader classLoader = proxyObject.getClass().getClassLoader();
- //需要代理的接口,被代理类实现的多个接口都必须在这里定义 (这是一个缺陷,cglib弥补了这一缺陷)
- Class<?>[] proxyInterface = proxyObject.getClass().getInterfaces();//new Class[]{};
- //织入器,织入代码并生成代理类
- return Proxy.newProxyInstance(classLoader,
- proxyInterface, this);
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- PersonServiceBean bean = (PersonServiceBean)this.proxyObject;
- Object result = null;
- //控制哪些用户执行切入逻辑
- if(bean.getUser() != null) {
- //执行原有逻辑
- result = method.invoke(this.proxyObject, args);
- }
- return result;
- }
- }
- package com.tech.junit;
- import org.junit.BeforeClass;
- import org.junit.Test;
- import com.tech.jdkproxy.JDKProxyFactory;
- import com.tech.service.PersonService;
- import com.tech.service.impl.PersonServiceBean;
- public class PersonTest {
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- }
- @Test
- public void Test() {
- JDKProxyFactory factory = new JDKProxyFactory();
- PersonService bean = (PersonService) factory
- .createProxyInstance(new PersonServiceBean("lucy"));
- //用户为lucy,有权限
- bean.save("abc");
- PersonService bean2 = (PersonService) factory
- .createProxyInstance(new PersonServiceBean());
- //用户为null,没有权限,不输出
- bean2.save("abc");
- }
- }
但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。