手动写出一个静态代理
在一个实现的类上,不修改原来实现类的部分来进行扩展。代理类是在原来的基础上进行扩展的功能的,与用户直接交互的是代理
举例:
接口:
public interface UserDao {
void insert();
}
被代理的对象
public class UserDaoImpl implements UserDao {
public void insert() {
System.out.println("将数据插入数据库成功");
}
}
代理类
public class UserDaoImplProxy implements UserDao {
private UserDao userDaoImpl;
public UserDaoImplProxy(UserDao userDaoImpl) {
this.userDaoImpl = userDaoImpl;
}
public void insert() {
System.out.println("在插入之前进行权限检查");
userDaoImpl.insert();
System.out.println("在插入之后将日志记录完成");
}
}
测试
@org.junit.Test
public void test2(){
UserDao userDaoImpl = new UserDaoImpl();
UserDao userDaoImplProxy = new UserDaoImplProxy(userDaoImpl);
userDaoImplProxy.insert();
}
缺点:静态的代理过程中,如果实现的接口的数目过多的话,随之而来的静态的代理类就会原来越多,不利于维护。
jdk进行动态的代理
特点:
1)不需要实现接口
2)动态的在内存中创建一个代理的对象(也就是在类加载的过程中进行代理)
接口:
public interface UserDao {
void update();
}
实现类:
public class UserDaoImpl implements UserDao {
public void update() {
System.out.println("userdao的update的方法执行了");
}
}
实现InvocationHandler接口然后重写方法生成代理:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author kiosk
*/
public class UserDaoInvocation implements InvocationHandler {
/**
* 需要被代理的对象
*/
private Object target;
public UserDaoInvocation(Object target){
this.target = target;
}
/**
* 给目标对象生成代理对象
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
method.invoke(target,null);
after();
return null;
}
public void before(){
System.out.println("修改之前进行权限的检查");
}
public void after(){
System.out.println("日志记录");
}
}
测试:
public class Test {
@org.junit.Test
public void test1(){
UserDaoInvocation invocation = new UserDaoInvocation(new UserDaoImpl());
ClassLoader loader = Test.class.getClassLoader();
Class<?>[] classes = UserDaoImpl.class.getInterfaces();
UserDao o = (UserDao)Proxy.newProxyInstance(loader, classes, invocation);
o.update();
}
}
动态代理过程
(1)Proxy通过传递给它的参数(interfaces/invocationHandler)生成代理类$Proxy0;
(2)Proxy通过传递给它的参数(ClassLoader)来加载生成的代理类$Proxy0的字节码文件;
cglib动态代理实现
特点:jdk实现代理的模式是要实现一个接口,cglib的动态的代理是不用让被代理的类实现一个接口。
(1)目标类
public class UserService {
public UserService(){
}
public void register(){
System.out.println("register的方法");
}
public final void power(){
System.out.println("power的方法");
}
}
(2)代理
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* cglib采用的方式是继承来产生继承的对象
*/
public class MyMethodInterceptor implements org.springframework.cglib.proxy.MethodInterceptor {
private UserService userService;
public MyMethodInterceptor(UserService userService){
this.userService = userService;
}
/**
* 生成代理对象并且进行返回
* @return
*/
public UserService createUserService(){
//创建cglib的核心对象
Enhancer enhancer = new Enhancer();
//设置父类对象
enhancer.setSuperclass(userService.getClass());
//设置回调(相当于是InvocationHandler对象)
enhancer.setCallback(this);
//生成代理对象并且进行返回
UserService o = (UserService)enhancer.create();
return o;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("权限的检查");
method.invoke(userService,null);
System.out.println("日志的记录");
return null;
}
}
(3)测试
public class TestCGlib {
@Test
public void test(){
UserService userService = new MyMethodInterceptor(new UserService()).createUserService();
userService.register();
}
}