Spring框架之代理

代理模式

模拟场景:
            房东       黑中介     住户
        任务:
        房东:把房出租,换点零花钱
        中介:帮房东出租房屋(最基本的任务),获取中介费
        住户:有床就行
代理模式图:

代理模式图

代理的特点:
    (1)代理对象和目标对象(被代理者)共同实现一个借口
    (2)代理对象要完成自己本职的工作(给房东租房),还要完成自己的额外的操作(收中介费)
代理的意义:
    在完成了自己的本职工作的时候,还完成了额外的扩展
具体代码实现:
                        package cn.tedu.pojo;
                        /**
                         * 定义接口,目标对象和代理对象都要实现这个接口
                         * @author tedu
                         *
                         */
                        public interface Rent {
                            public void rent();
                        }

                        package cn.tedu.pojo;
                        /**
                         * 中介
                         * 完成买房子 还要收取费用
                         * @author tedu
                         *
                         */
                        public class Proxy implements Rent {
                            //调用目标类 完成目标类的任务
                            private House house = new House();
                            @Override
                            public void rent() {
                                //完成目标类的任务
                                house.rent();
                                //完成自己的任务,实现扩展
                                System.out.println("代理类:收取中介费");
                            }

                        }

                        package cn.tedu.pojo;
                        /**
                         * 目标类 即房东出租房子
                         * @author tedu
                         *
                         */
                        public class House implements Rent{

                            @Override
                            public void rent() {
                                System.out.println("目标类:房东出租房屋");
                            }

                        }

                        package cn.tedu.pojo;
                        /**
                         * 租房者 找代理类租房子
                         * @author tedu
                         *
                         */
                        public class Client {
                            public static void main(String[] args) {
                                //创建代理类
                                Proxy proxy = new Proxy();
                                //租房子
                                proxy.rent();
                            }
                        }

静态代理:

    用户调用代理类 代理类调用被代理类,并添加一些自己额外扩展的东西. 

    模拟场景:
        使用分层,在添加用户的时候,实现事务的管理,事务的管理一般放在service层
    具体方法:
        (1)代理类和目标类实现同一个接口
        (2)在静态代理类中调用目标类的方法,并添加控制
    代码分析:
        (1)使用注解,要配置xml文件 开启包扫描
        (2)创建代理类 事务类 
    自己的理解:
        就是创建一个静态代理类和目标类实现用一个接口,在接口里面调用事务,用户在调用的时候表面是调用的是目标对象,
        实际上调用的是代理对象,当共同实现一个接口的时候会发生风险,所以更改类的id,修改静态代理的id名字,和目标类
        的id名字.
                    //代码实现
                    //配置文件的写法:
                    <context:component-scan base-package="dao,service,servlet,tx,proxy"/>



                        ----------


                        //事务类
                        package tx;

                        import org.springframework.stereotype.Component;

                        @Component
                        public class TransactionManager {

                            public void begin(){
                                System.out.println("事务开启");
                            }

                            public void commit(){
                                System.out.println("事务提交");
                            }

                            public void rollback(){
                                System.out.println("事务回滚");
                            }
                        }


                        ----------


                        //servlet层
                        package servlet;

                        import org.springframework.beans.factory.annotation.Autowired;
                        import org.springframework.stereotype.Controller;

                        import service.UserService;

                        @Controller //id为userServlet
                        public class UserServlet {
                            @Autowired
                            private UserService userService;//面向切面编程

                            public void addUser(){
                                userService.addUser();
                            }
                        }


                        ----------


                        //service层
                        package service;

                        public interface UserService {

                            public void addUser();

                        }


                        package service;

                        import org.springframework.beans.factory.annotation.Autowired;
                        import org.springframework.stereotype.Service;

                        import dao.UserDao;

                        @Service("target") //目标类 被代理的类
                        public class UserServiceImpl implements UserService{
                            @Autowired
                            private UserDao userDao;
                            @Override
                            public void addUser() {
                                userDao.addUser();
                            }

                        }

                        ----------


                        //dao层
                        package dao;

                        public interface UserDao {
                            public void addUser();

                        }

                        package dao;

                        import org.springframework.stereotype.Repository;

                        @Repository
                        public class UserDaoImpl implements UserDao {

                            @Override
                            public void addUser() {
                                System.out.println("添加一个用户");
                            }

                        }


                        ----------


                        //测试类
                        package text;

                        import org.junit.Test;
                        import org.springframework.context.ApplicationContext;
                        import org.springframework.context.support.ClassPathXmlApplicationContext;

                        import service.UserService;

                        public class TestSpring {
                            @Test
                            public void Test(){
                                ApplicationContext context = 
                                new ClassPathXmlApplicationContext("applicationContext.xml");
                                //调用的是代理类
                                UserService service =(UserService) context.getBean("userService");
                                service.addUser();

                            }
                        }
静态代理的优点和缺点:
    优点:能够将业务处理和事务控制进行分类,实现解耦
    缺点:(1)当添加的事务多的时候,代码大量重复,
        (2)只能处理一类业务,如果要处理其他的业务,需要重新定义代理对象,代理对象不能通用,灵活性低

动态代理

动态代理分为:jdk动态代理和CgLib动态代理:
    1.jdk动态代理
    解决静态代理的不灵活性,可以添加多个业务
    实现方法:
        写一个静态代理方法传入,传入目标类和,要添加的事物
        核心方法:Proxy.newProxyInstance(类加载器,获取所有的接口,new InvocationHandler(){
        匿名内部类,重写invoke方法});
        实现代码:
        dao service servlet tx 层的代码和静态的一样
/**
 * 动态代理
 * @author acer
 *
 */
public class DynamicProxy {
    //为方法添加事物操作操作                   //目标方法      //事物管理类
    public static Object getProxy(final Object target,final TransactionManager tx){
        Object proxy=Proxy.newProxyInstance(target.getClass().getClassLoader(),//类加载器
                target.getClass().getInterfaces(), //所有的接口
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        Object result = null;
                        System.out.println("动态代理开始");
                        tx.begin();
                        //反射执行目标方法
                        method.invoke(target, args);
                        tx.commit();
                        System.out.println("动态代理结束");
                        return result;
                    }
                });
        return proxy;
    }
}
//测试类
package text;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import proxy.DynamicProxy;

import service.UserService;
import tx.TransactionManager;

public class TestString {
    @Test
    public void text01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取目标对象
        UserService target = (UserService) context.getBean("target");
        System.out.println(target.getClass());
        //获得事物类
        TransactionManager tx = (TransactionManager) context.getBean("tx");
        //通过动态代获取对象
        UserService userService = (UserService) DynamicProxy.getProxy(target, tx);
        userService.addUser();

    }
}
    2.CgLib动态代理:

        和jdk动态代理的实现差不多
        具体代码如下:

“`
package proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import tx.TransactionManager;

            /**
             * cgblib动态代理
             * @author tedu
             *
             */
            public class CgblibProxy {

                public static Object getProxy(final Object target ,final TransactionManager tx){
                    //1.创建增强器,操作的是二进制
                    Enhancer enhancer = new Enhancer();
                    //2.设置父类
                    enhancer.setSuperclass(target.getClass());
                    //3.如果有接口就实现接口
                    enhancer.setInterfaces(target.getClass().getInterfaces());
                    //4.设置回调接口方法        //相当于jdk动态代理中的 new InvocationHandler()
                    enhancer.setCallback(new MethodInterceptor() {

                        @Override       //jdk动态代理中的invoke()方法
                        public Object intercept(Object proxy, Method method, Object[] args,
                                MethodProxy arg3) throws Throwable {
                            Object result = null;
                            try{
                                System.out.println("cgblib动态代理开始");
                                tx.begin();//开启事务
                                result = method.invoke(target, args);
                                tx.commit();//提交事务
                                System.out.println("cgblib动态代理结束");
                            }catch(Exception e){
                                e.printStackTrace();
                                tx.rollback();//回滚事务
                            }
                            return result;
                        }
                    });
                    //返回代理对象
                    return enhancer.create();
                }
            }

    ```

    jdk动态代理和CgLib动态代理的区别:
            jdk动态代理需要目标对象必须和代理对象实现相同的接口,否则不能生成代理对象
            jdk动态代理生成的代理对象速度快, .java到.class 运行速度慢
            生成的代理对象为 class com.sun.proxy.$Proxy6
            CgLib动态代理不需要目标对象实现接口也能生成代理对象,因为代理对象是目标对象的子类
            CgLib动态代理生成代理对象的速度慢 .java到.calss到二进制 运行速度快,底层是二进制
            生成的代理对象为 class service.UserServiceImpl$$EnhancerByCGLIB$$34a01bb6

        jdk动态代理和CgLib动态代理的选择:
            一般都使用jdk动态代理的多,在有特定的环境下才使用CgLib动态代理,如果目标对象没用使用接口就用CgLib动态代理;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值