代理模式
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理:在程序运行时,运用反射机制动态创建而成。
静态代理:
Task .java
package cn.staticproxy.beanfactory;
public interface Task {
public void startTask();
public void doTask();
public void finishTask();
}
TaskImpl.java
package cn.staticproxy.service;
import cn.staticproxy.beanfactory.Task;
public class TaskImpl implements Task {
public void startTask() {
System.out.println("开始任务");
}
public void doTask() {
System.out.println("执行任务");
}
public void finishTask() {
System.out.println("完成任务");
}
}
TaskFactory .java
package cn.staticproxy.bean;
import cn.staticproxy.beanfactory.Task;
import cn.staticproxy.service.TaskImpl;
public class TaskFactory implements Task {
private TaskImpl taskImpl=null;
public TaskFactory(TaskImpl taskImpl) {
this.taskImpl = taskImpl;
}
public void startTask() {
System.out.println("代理-->开始任务");
taskImpl.startTask();
}
public void doTask() {
System.out.println("代理-->执行任务中");
taskImpl.doTask();
}
public void finishTask() {
System.out.println("代理-->完成任务");
taskImpl.finishTask();
}
}
TaskTest .java
import org.junit.Test;
import cn.staticproxy.bean.TaskFactory;
import cn.staticproxy.service.TaskImpl;
public class TaskTest {
@Test
public void test(){
TaskImpl taskImpl =new TaskImpl();
TaskFactory taskFactory =new TaskFactory(taskImpl);
taskFactory.startTask();
taskFactory.doTask();
taskFactory.finishTask();
}
}
静态代理每一个只能为一个接口服务,会产生很对代理类,所有代理类除了调用方法不同外其他会有很多相同的部分,会有重复代码,解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。
动态代理:
Proxy类
Proxy.newProxyInstance(ClassLoader loader, <Class<?>[] interfaces,InvocationHandler h);
ClassLoaderoader:类加载器(谁去装载这个类)
<Class<?>[] interfaces:类的全部接口
InvocationHandler h:代理实例关联的调用处理程序(回调函数)
InvocationHandler 接口
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
proxy:指被代理的对象。
Method method:调用的方法
Object[] args:方法接受的参数
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
PersonService.java
package cn.proxy.service;
public interface PersonService {
public String save(String name);
public void delete(Integer id);
public void update(String name);
public void find(Integer id);
public String save();
}
PersonServiceBean .java
package cn.proxy.service.impl;
import cn.proxy.service.PersonService;
public class PersonServiceBean implements PersonService {
public PersonServiceBean(String name) {
this.name = name;
}
public String name="";
public String save() {
System.out.println("我是"+name+"的save方法");
return name;
}
public void delete(Integer id) {
System.out.println("我是delete方法");
}
public void update(String name) {
System.out.println("我是update方法");
}
public void find(Integer id) {
System.out.println("我是find方法");
}
public String save(String name) {
System.out.println("我是"+name+"的save方法");
return name;
}
public String getName() {
return name;
}
}
ProxyFactoryBean.java
package cn.proxy.factory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import cn.proxy.service.PersonService;
import cn.proxy.service.impl.PersonServiceBean;
public class ProxyFactoryBean implements InvocationHandler {
private Object targeObj;
public Object getInstance(Object obj){
this.targeObj=obj;
return Proxy.newProxyInstance(this.targeObj.getClass().getClassLoader(), this.targeObj.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//环绕通知
PersonServiceBean ps= (PersonServiceBean) this.targeObj;
Object result=null;
if(ps.getName()!=null){
try {
//..... advice()-->前置通知
advice();
result = method.invoke(targeObj, args);
afterAdvice();
//..... afterAdvice()-->后置通知
} catch (Exception e) {
//.....例外通知
}finally{
//...最终通知
}
}
return result;
}
private void afterAdvice() {
System.out.println("后置通知");
}
private void advice() {
System.out.println("前置通知");
}
}
ProxyTest .java
package cn.proxy.junit;
import org.junit.Test;
import cn.proxy.factory.ProxyFactoryBean;
import cn.proxy.service.PersonService;
import cn.proxy.service.impl.PersonServiceBean;
public class ProxyTest {
@Test
public void Test(){
ProxyFactoryBean pfb=new ProxyFactoryBean ();
PersonService ps = (PersonService) pfb.getInstance(new PersonServiceBean("aaa"));
ps.save();
}
}
CGlib实现:
package cn.proxy.service.impl;
import cn.proxy.service.PersonService;
public class PersonServiceBean {
//implements PersonService {
public PersonServiceBean(String name) {
this.name = name;
}
public PersonServiceBean() {
}
public String name="";
public String save() {
System.out.println("我是"+name+"的save方法");
return name;
}
public void delete(Integer id) {
System.out.println("我是delete方法");
}
public void update(String name) {
System.out.println("我是update方法");
}
public void find(Integer id) {
System.out.println("我是find方法");
}
public String save(String name) {
System.out.println("我是"+name+"的save方法");
return name;
}
public String getName() {
return name;
}
}
package cn.proxy.factory;
import java.lang.reflect.Method;
import cn.proxy.service.impl.PersonServiceBean;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibFactory implements MethodInterceptor {
private Object tarobject;
public Object getInstance(Object obj){
this.tarobject=obj;
Enhancer enhancer =new Enhancer();
enhancer.setSuperclass(this.tarobject.getClass());//非final,获取目标类,自动创建子类,覆盖目标类中非final方法
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
//环绕通知
PersonServiceBean ps= (PersonServiceBean) this.tarobject;
Object result =null;
if(ps.getName()!=null){
result = method.invoke(tarobject, args);
}
return result;
}
}
测试类:
@Test
public void cglibTest(){
CGLibFactory pfb=new CGLibFactory() ;
PersonServiceBean ps = (PersonServiceBean) pfb.getInstance(new PersonServiceBean("aaa"));
ps.save();
}
解释:
他与jdk'原生的代理不同的是
1.PersonServiceBean没有实现PersonService接口,
2.enhancer.setSuperclass(this.tarobject.getClass());//非final,获取目标类,自动创建子类,覆盖目标类中final方法
enhancer.setCallback(this);
return enhancer.create();
创建的是目标类的子类对象,
注意被代理的类中要有无参的构造方法,如果有参数net.sf.cglib.proxy.Enhancer.create(Class[], Object[])这个方法
3.CGlibProxyFactory implements MethodInterceptor
所以要我们的代理工厂要实现MethodInterceptor这个接口.
覆写intercpter方法