一、概念
二、静态代理
三、动态代理
四、Cglib代理
代理模式—种设计模式,提供了对目标对象的另外的访问方式即通过代理访问目标对象
好处:1、可以在目标对象实现的基础上,增加额外的功能的操作
2、扩展目标对象的功能
保存数据到数据库Dao直接保存
添加事务
要求:代理对象,要实现与目标对象一样的接口
优点:可以做到不修改目标对象功能前提下,对目标对象扩展。
缺点∶因为代理对象需要实现与目标对象相同的接口,会有很多代理类一旦接口增加方法,目标对
象与代理对象都需要维护
解决方式:代理工厂,动态代理
package com.iotek.staticPackage;
public interface UserDao {
public void save();
}
package com.iotek.staticPackage;
/**
* @Author:目标对象
* @CreateTime: 2023-01-05 12:28
*/
public class UserDaoImpl implements UserDao{
@Override
public void save() {
System.out.println("-----------------数据已保存到数据库-----------------");
}
}
package com.iotek.staticPackage;
/**
* @Author:代理对象静态代理方式)
* @CreateTime: 2023-01-05 12:30
*/
public class UserDaoProxy implements UserDao{
private UserDao userDao;
public UserDaoProxy(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
System.out.println("开始事务");
userDao.save();
System.out.println("提交事务");
}
}
package com.itoek.staticPackage;
/**
* @Author:
* @CreateTime: 2023-01-05 12:35
*/
public class Test {
public static void main(String[] args) {
/*目标对象*/
UserDao userDao = new UserDaoImpl();
/*代理对象*/
UserDao userDaoProxy = new UserDaoProxy(userDao);
userDaoProxy.sava();
}
}
代理对象不需要实现接口
代理对象生成,使用到JDKAPI,动态的在内存中创建代理对象
动态代理,也叫JDK代理,接口代理
public static Object newProxyInstance(ClassLoader loader,//指定当前目标对象的使用类的加载器
Class[] interfaces,//目标实现的接口类型
InvocationHandler h//事件处理器)
目标对象一定要实现接口,否则不能使用动态代理
class $Proxy0 implements XXX
package com.iotek.dynamic;
public interface UserDao {
public void save();
public void update();
}
package com.iotek.dynamic;
/**
* @Author:目标对象
* @CreateTime: 2023-01-05 12:28
*/
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("-----------------数据已保存到数据库-----------------");
}
@Override
public void update() {
System.out.println("-----------------数据已修改-----------------");
}
}
package com.iotek.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author:
* @CreateTime: 2023-01-05 12:45
*/
public class ProxyFactory {
private Object target;//目标对象
public ProxyFactory(Object target) {
this.target = target;
}
/*生成代理对象*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),//目标对象加载器
target.getClass().getInterfaces(),//目标兑现所实现的接口
new InvocationHandler() {//事件处理器
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务");
Object result = method.invoke(target,args);//调用目标对象方法
System.out.println("结束事务");
return result;
}
}
);
}
}
package com.iotek.dynamic;
/**
* @Author:
* @CreateTime: 2023-01-05 12:43
*/
public class Test {
/*目标对象*/
public static void main(String[] args) {
/*目标对象*/
UserDao userDao = new UserDaoImpl();
/*代理对象 class com.sun.proxy.$Proxy0内存中动态生成的代理对象*/
UserDao proxy = (UserDao) new ProxyFactory(userDao).getProxyInstance();
proxy.save();
proxy.update();
System.out.println(proxy.getClass());
}
}
有一个目标对象,没有接口
子类代理。在内存中构建一个子类对象从而实现对目标对象的扩展
Cglib许多AOP框架使用
步骤︰
引用.jar文件---Spring Core包中包含
在内存中动态创建目标对象的子类
目标对象不可以是final
目标对象方法是final、static,则不会拦截
在Spring AOP编程中
如果加入容器中的目标对象有实现接口,用IDK代理
如果目标对象没有有实现接口,用cglib代理
package com.iotek.cglib;
/**
* @Author:目标对象
* @CreateTime: 2023-01-05 12:28
*/
public class UserDaoImpl {
public void save() {
System.out.println("-----------------数据已保存到数据库-----------------");
}
public void update() {
System.out.println("-----------------数据已修改-----------------");
}
}
package com.iotek.cglib;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Author:cglib子类代理工厂(对Use人Dao在内存中动态创建一个代理)
* @CreateTime: 2023-01-05 14:16
*/
public class ProxyFactory implements MethodInterceptor {
/*目标对象*/
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/*代理对象*/
public Object getProxyInstance(){
/*1、工具类*/
Enhancer enhancer = new Enhancer();
/*2、设置父类*/
enhancer.setSuperclass(target.getClass());
/*3、设置回调*/
enhancer.setCallback(this);
/*4、创建代理对象*/
return enhancer.create();
}
/*方法拦截器接口*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
/*执行目标对象的方法*/
System.out.println("开始事务");
Object resultValue = method.invoke(target,objects);
System.out.println("结束事务");
return resultValue;
}
}
package com.iotek.cglib;
/**
* @Author:
* @CreateTime: 2023-01-05 14:38
*/
public class Test {
public static void main(String[] args) {
/*目标对象*/
UserDaoImpl userDaoImpl = new UserDaoImpl();
/*代理对象*/
UserDaoImpl proxy = (UserDaoImpl) new ProxyFactory(userDaoImpl).getProxyInstance();
proxy.save();
proxy.update();
System.out.println(proxy.getClass());
}
}