将通用性的工作都交给代理对象完成,被代理对象只专注自己的核心业务。
1.被代理类中只用关注核心业务的实现,将通用的管理型逻辑(事务管理,日志管理)和业务逻辑分离。
2.将通用的代码放在代理类中实现,提高了代码的复用性
3.通过在代理类添加业务逻辑,实现对原有业务逻辑的扩展(增强)
静态代理,代理类只能够为特定的类生产代理对象,不能代表任意类
GenaraDAOpublic interface GenaraDAO {
public void insert();
public void delect();
public void update();
}
StaticProxy(代理类)
public class StaticProxy {
private GenaraDAO genaraDAO;
public StaticProxy(GenaraDAO genaraDAO) {
this.genaraDAO = genaraDAO;
}
public void insert(){
begin();
genaraDAO.insert();
commmit();
}
public void delete(){
begin();
genaraDAO.delect();
commmit();
}
public void update(){
begin();
genaraDAO.update();
commmit();
}
public void begin(){
System.out.println("-------开启事务");
}
public void commmit(){
System.out.println("-------提交事务");
}
}
StudentDAO(被代理类)
public class StudentDAO implements GenaraDAO{
@Override
public void insert() {
System.out.println("-------添加学生");
}
@Override
public void delect() {
System.out.println("-------删除学生");
}
@Override
public void update() {
System.out.println("-------更新学生信息");
}
}
BookDAO(被代理类)
@Override
public void insert() {
System.out.println("-------添加书籍");
}
@Override
public void delect() {
System.out.println("-------删除书籍");
}
@Override
public void update() {
System.out.println("-------更新书籍信息");
}
#####Test
@Test
public void test1(){
//被代理对象
BookDAO b
ookDAO = new BookDAO();
//为被代理对象创建代理对象
StaticProxy proxy = new StaticProxy(bookDAO);
proxy.delete();
}
动态代理
动态代理,几乎可以为所有的类产生代理对象
动态代理的实现方式有两种:
1.JDK动态代理
2.CGLib动态代理
JDK动态代理:是通过被代理对象实现的接口产生其代理对象
1.创建一个类实现InvocationHandler接口,重写invoke方法
2.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于将被代理对象传递进来
3.创建getProxy方法,用于创建并返回代理对象
//JDK动态代理:是通过被代理对象实现的接口产生其代理对象
//1.创建一个类实现InvocationHandler接口,重写invoke方法
//2.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于将被代理对象传递进来
//3.创建getProxy方法,用于创建并返回代理对象
public class JDKDynamicProxy implements InvocationHandler{
//被代理对象
private Object obj;
public JDKDynamicProxy(Object obj) {
this.obj = obj;
}
//产生代理对象,返回代理对象
public Object getProxy(){
//1.获取被代理对象的类加载器
ClassLoader classLoader = obj.getClass().getClassLoader();
//2.获取被代理对象的类实现的接口
Class>[] interfaces = obj.getClass().getInterfaces();
//3.产生代理对象
//第一个参数是被代理对象的类加载器
//第二个参数是被代理对象实现的接口
//第三个参数是产生代理对象调用方法时,用于拦截方法执行的拦截器
Object o = Proxy.newProxyInstance(classLoader, interfaces,this);
return o;
}
@Override
//method就是调用的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
begin();
Object returnValue = method.invoke(obj);
commit();
return returnValue;
}
public void begin(){
System.out.println("-------开始事务");
}
public void commit(){
System.out.println("-------提交事务");
}
}
Test
@Test
public void test2(){
//被代理对象
BookDAO bookDAO = new BookDAO();
//创建动态代理对象,并将被代理对象传递到道理对象中,赋值给obj
//proxy就是BookDAO的代理对象:可以强转成被代理对象的接口类型
GenaraDAO proxy = (GenaraDAO)new JDKDynamicProxy(bookDAO).getProxy();
//代理对象调用方法,并不会执行调用的方法,而是进入到创建代理对象时指定的InvocationHandler中的invoke方法
//调用的方法作为一个Method参数,传递给了invoke方法
proxy.delect();
}
由于JDK动态代理是通过被代理类实现的接口来创建代理对象的,因此JDK动态代理,只能代理实现了接口的类的对象。如果一个类没有实现任何接口,我们应该使用CGLib代理
CGLib动态代理CGLib动态代理,是通过创建被代理类的子类来创建代理对象的,因此即使没有实现任何接口的类也可以通过CGLib产生代理对象。
CGLib动态代理不能为final类创建代理对象
CGLib动态代理实现cglib cglib 3.3.0
//1.添加cglib依赖
//2.创建一个类实现MethodInterceptor接口,同时实现接口中的intercept方法
//3.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于传递被代理对象
//4.定义getProxy方法进行传递返回代理对象(代理对象是通过 创建被代理类的子类来创建的)
public class CGLibDynamicProxy implements MethodInterceptor {
private Object obj;
public CGLibDynamicProxy(Object obj) {
this.obj = obj;
}
//产生代理的过程
public Object getProxy(){
Enhancer enhancer = new Enhancer();
//把被代理对象设为父类
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
Object proxy = enhancer.create();
return proxy;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
begin();
Object returenValue = method.invoke(obj,objects);//通过反射调用被代理类的方法
commit();
return returenValue;
}
public void begin(){
System.out.println("-------开始事务");
}
public void commit(){
System.out.println("-------提交事务");
}
}
Test
@Test
public void test3(){
//创建被代理对象
BookDAO bookDAO = new BookDAO();
//创建代理对象
CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(bookDAO);
//代理对象实际上是被代理对象的子类,因此代理对象可以直接被强转为代理类型
BookDAO proxy = (BookDAO) cgLibDynamicProxy.getProxy();
//使用代理对象调用方法,实际上并没有执行这个方法,而是执行了代理类中的intercept方法,将当前调用的方法,以及方法中的参数传递到intercept方法
proxy.update();
}



