您的位置:首页 > 编程语言 > Java开发

Spring 静态代理和动态代理实现

2017-12-28 22:23 417 查看
静态代理是为了在代理类的前后加上各种需要的东西,而且还不改变其本身的方法,实现方法就是在其父类的接口下重新创建一个类,来实现要代理的类的父类,然后重写方法(重写是为了方法名一样,返回值类型和参数一样),在内部调用其被代理类的方法,在前后加上事物,日志,时间之类

接口

package com.sxt.dao;

public interface UserDao {

public void save() throws Exception;
}


被代理的类

package com.sxt.dao.impl;

import com.sxt.dao.UserDao;

public class UserDaoimpl implements UserDao {

public void save() throws Exception {
System.out.println("调用了save方法保存");
}

}


代理类

package com.sxt.dao.impl;

import com.sxt.dao.UserDao;

public class UserProxy implements UserDao {
private UserDao dao;
public void save() throws Exception {

System.out.println("事物,权限, 日志开启");
dao.save();
System.out.println("事物,权限,日志关闭");
}
public UserDao getDao() {
return dao;
}
public void setDao(UserDao dao) {
this.dao = dao;
}
}


调用的时候直接调用代理类,代理类内部会调用被代理的类, 并且前后加了一些东西, 这就是静态代理的实现方法

动态代理 :为了解决静态代理每有一个被代理类就要创建一个代理类的弊端,出现了动态代理,动态代理是把所有东西都抽取出来了

接口

package com.sxt.dao;

public interface UserDao {

public void save() throws Exception;
}


被代理的类

package com.sxt.dao.impl;

import com.sxt.dao.UserDao;

public class UserDaoimpl implements UserDao {

public void save() throws Exception {
System.out.println("调用了save方法保存");
}

}


动态代理类:基于兄弟类

package com.sxt.util;

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

public class MyProxy implements InvocationHandler {
private Object target;// 被代理者

public  Object getProxy(Object o) {
this.target=o;//o就是传过来的被代理者

/**
*      第一个参数:this.getClass().getClassLoader() - 定义代理类的类加载器
第二个参数:interfaces - 被代理类的父类的接口
第三个参数:h - 指派方法调用的调用处理程序(应该是谁来代理)
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//调用代理类的代理方法   Object proxy 谁来代理  Method method 方法 Object[] args 参数
public Object invoke(Object proxy,Method method,Object[] args) throws Exception{
System.out.println("事物开启");
//target 被代理的那个类   args 要什么参数 Object b返回值
Object b = method.invoke(target, args);//执行你要执行的方法,前后为事物控制

System.out.println("事物结束");
return b;
}
}


测试

package com.sxt.test;

import com.sxt.dao.UserDao;
import com.sxt.dao.impl.UserDaoimpl;
import com.sxt.util.MyProxy;

public class Test {
public static void main(String[] args) {

/**
* 动态代理
*/

UserDao dao = new UserDaoimpl();//被代理的对象
MyProxy dt = new MyProxy();
Object proxy = dt.getProxy(dao);//返回出来的就是代理类,只是这个代理类不用你创建,而是系统给你创建好了

try {

dt.invoke(proxy,dao.getClass().getDeclaredMethod("save", null), null);

} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

}
}


基于父类实现动态代理: cglib动态代理. 本质上动态生成了一个被代理目标的子类(要求被代理类不是final修饰的类),通过多态实现功能的加强,当访问代理中的方法时, 委派给MethodInteceptor中的处理程序(intercept方法)进行出来, 在处理程序中添加了业务逻辑和回掉了被代理目标中的方法。

添加cglib-2.2.2.jar

<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>


动态代理

package com.sxt.util;

import java.lang.reflect.Method;

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

public class MyProxy1 implements MethodInterceptor {
private Object target;

public Object getProxy(Object target){
Enhancer enhancer = new Enhancer();
//1.设置基类
enhancer.setSuperclass(target.getClass());
//2.设置回调接口
enhancer.setCallback(this);//MethodInterceptor实现类
//3.创建动态代理
return enhancer.create();

}

public Object intercept(Object proxy, Method m, Object[] os,
MethodProxy mp) throws Throwable {
Object o = m.invoke(target, os);
return o;
}
}


测试

package com.sxt.test;

import com.sxt.dao.UserDao;
import com.sxt.dao.impl.UserDaoimpl;
import com.sxt.util.MyProxy1;
/**
* 用子类做代理
* @author Administrator
*
*/
public class Test2 {
public static void main(String[] args) {

UserDao dao = new UserDaoimpl();
MyProxy1 dt = new MyProxy1();
Object proxy = dt.getProxy(dao);
try {
dt.intercept(proxy, dao.getClass().getDeclaredMethod("save", null), null,null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}
}


和上面那个兄弟类出面做事情差不多,只是设置的时候不一样而已
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: