spring学习笔记 -- day06 动态代理

来源:互联网 发布:python 日期时间差 编辑:程序博客网 时间:2024/06/05 18:10

一、基于接口的动态代理

1、被代理的类实现的接口

package cn.itcast.proxy;/** * 经纪公司的签约演员的规范 * @author zhy * */public interface IActor {public void basicAct(float money);public void dangerAct(float money);}

2、被代理的类

package cn.itcast.proxy;/** * 演员类动作类* @Description: TODO* @author wingzhe   */public class Actor implements IActor {public void basicAct(float money){System.out.println("拿到"+money+"元,开始表演");}public void dangerAct(float money) {System.out.println("拿到"+money+"元,开始进行危险动作");}}

3、实现代理功能

package cn.itcast.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Client {/** *  模拟一个剧组 * @param args */public static void main(String[] args) {final Actor actor = new Actor();/** * Proxy: * 用于创建代理对象的类。是JDK官方提供的 *  使用newProxyInstance方法创建。 *  创建的要求:被代理对象必须最少实现一个接口 * newProxyInstance方法的参数: * ClassLoader:和被代理对象使用相同的类加载器。 *  Class[]:和被代理对象具有相同的行为(实现相同的接口) *  InvocationHandler:一般情况下是一个匿名内部类,提供invoke方法的实现。 *    在invoke方法中写的,就是增强部分的代码。 *  简单的说,这个参数它的含义就是:如何代理。 *  此接口的实现类(匿名内部类):谁用谁写。 *  策略模式: *  数据已经有了 *  目的明确 * 如何达成目标:谁用谁写。写出来的就是策略。 *  * 动态代理的作用: * 在不修改源码的基础上,运行期间对方法进行增强 */IActor proxyActor = (IActor) Proxy.newProxyInstance(actor.getClass().getClassLoader(), actor.getClass().getInterfaces(), new InvocationHandler() {/** * 执行被代理对象的任何方法,都会经过该方法。此方法有拦截功能 * 参数详解: * Object proxy:代理对象的引用 * Method method:当前执行的方法对象 *  Object[] args:执行方法时所需的参数 * 返回值: * Object:当前执行方法的返回值 */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object rtValue = null;//1.取出moneyFloat money = (Float)args[0];//2.判断如果基本的表演,没有2000块钱,不演if("basicAct".equals(method.getName())){if(money > 2000){rtValue = method.invoke(actor, money/2);}}//3.判断如果是危险表演,没有20000块钱,不演if("dangerAct".equals(method.getName())){if(money > 20000){rtValue = method.invoke(actor, money/2);}}return rtValue;}});//actor.basicAct(500);//actor.dangerAct(1000);proxyActor.basicAct(5000);proxyActor.dangerAct(100000);}}

二、基于子类的动态代理

1、创建项目,导入第三方jar包


2、创建被代理类

package cn.itcast.cglib;/** * 一个演员 * @author zhy * */public class Actor {public void basicAct(float money){System.out.println("拿到钱,开始基本的表演:"+money);}public void dangerAct(float money){System.out.println("拿到钱,开始危险的表演:"+money);}}

3、创建执行动作的代理类

package cn.itcast.cglib;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 Client {public static void main(String[] args) {final Actor actor = new Actor();/** * Enhancer: * 它是cglib提供的一个类,用于创建代理对象的。 * create方法是创建代理对象的方法。 * 使用要求:被代理对象不能是最终类。(类不能被final修饰) * 方法的参数: *  Class:被代理对象的字节码 *  Callback:如何代理。(也是策略模式) */Actor cglibActor = (Actor)Enhancer.create(actor.getClass(), new MethodInterceptor() {/** * 执行被代理对象的任何方法,都会经过该方法。此方法也有拦截的功能。 * 和InvocationHandler中的invoke方法作用是一样的 * 方法的参数: *  前面三个参数和invoke方法中的含义一模一样。 * MethodProxy methodProxy:当前执行方法的代理对象。 *  * 方法的返回值: * 当前执行方法的返回值 */@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object rtValue = null;//1.取出moneyFloat money = (Float)args[0];//2.判断如果基本的表演,没有2000块钱,不演if("basicAct".equals(method.getName())){if(money > 2000){rtValue = method.invoke(actor, money/3);}}//3.判断如果是危险表演,没有20000块钱,不演if("dangerAct".equals(method.getName())){if(money > 20000){rtValue = method.invoke(actor, money/3);}}return rtValue;}});cglibActor.basicAct(8000);cglibActor.dangerAct(60000);}}

三、动态代理实现事务控制

1、编写javaBean

package cn.itcast.domain;import java.io.Serializable;/** * 客户的实体类 * @author zhy * */public class Customer implements Serializable {private Long custId;private String custName;private String custSource;private String custIndustry;private String custLevel;private String custAddress;private String custPhone;public Long getCustId() {return custId;}public void setCustId(Long custId) {this.custId = custId;}public String getCustName() {return custName;}public void setCustName(String custName) {this.custName = custName;}public String getCustSource() {return custSource;}public void setCustSource(String custSource) {this.custSource = custSource;}public String getCustIndustry() {return custIndustry;}public void setCustIndustry(String custIndustry) {this.custIndustry = custIndustry;}public String getCustLevel() {return custLevel;}public void setCustLevel(String custLevel) {this.custLevel = custLevel;}public String getCustAddress() {return custAddress;}public void setCustAddress(String custAddress) {this.custAddress = custAddress;}public String getCustPhone() {return custPhone;}public void setCustPhone(String custPhone) {this.custPhone = custPhone;}}

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.itcast.domain"><class name="Customer" table="cst_customer"><id name="custId" column="cust_id"><generator class="native"></generator></id><property name="custName" column="cust_name"></property><property name="custIndustry" column="cust_industry"></property><property name="custSource" column="cust_source"></property><property name="custLevel" column="cust_level"></property><property name="custAddress" column="cust_address"></property><property name="custPhone" column="cust_phone"></property></class></hibernate-mapping>

2、编写Hibernate主配置文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- 1、连接数据库的基本信息 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/proxy</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">admin123</property><!-- 2、hibernate的基本配置 --><!-- 数据库的方言 --><property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><!-- 是否显示SQL语句 --><property name="hibernate.show_sql">true</property><!-- 是否格式化SQL语句 --><property name="hibernate.format_sql">true</property><!-- 是否让hibernate根据表结构的变化来生成DDL语句--><property name="hibernate.hbm2ddl.auto">update</property><!-- 配置数据源的提供商 --><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property><!-- 把session绑定到当前线程上 --><property name="hibernate.current_session_context_class">thread</property><!-- 3、映射文件的位置 --><mapping resource="cn/itcast/domain/Customer.hbm.xml"/></session-factory></hibernate-configuration>

3、编写HibernateUtil

package cn.itcast.utils;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;/** * hibernate的工具类 * 用于获取Session对象 *  * 使用工具类原因: * 1.简化代码 * 2.保证SessionFactory不会反复的创建和销毁 * */public class HibernateUtil {private static SessionFactory factory;static{try {Configuration cfg = new Configuration();cfg.configure();factory = cfg.buildSessionFactory();} catch (Exception e) {e.printStackTrace();throw new ExceptionInInitializerError("初始化SessionFactory失败!");}}/** * 每次都是从当前线程上获取Session * @return */public static Session getCurrentSession(){return factory.getCurrentSession();}/** * 开启事务 */public static void beginTransaction(){getCurrentSession().beginTransaction();}/** * 提交事务 */public static void commit(){getCurrentSession().beginTransaction().commit();}/** * 回滚事务 */public static void rollback(){getCurrentSession().beginTransaction().rollback();}}

4、编写Dao层代码

package cn.itcast.dao;import java.util.List;import cn.itcast.domain.Customer;/** * 客户的持久层接口 * */public interface ICustomerDao {/** * 保存客户 * @param customer */void saveCustomer(Customer customer);/** * 查询所有客户 * @return */List<Customer> findAllCustomer();/** * 删除客户 * @param customer */void removeCustomer(Customer customer);/** * 根据id查询客户 * @param custId * @return */Customer findCustomerById(Long custId);/** * 更新客户 * @param customer */void updateCustomer(Customer customer);}

package cn.itcast.dao.impl;import java.util.List;import cn.itcast.dao.ICustomerDao;import cn.itcast.domain.Customer;import cn.itcast.utils.HibernateUtil;/** * 客户的持久层实现类 * */public class CustomerDaoImpl implements ICustomerDao {@Overridepublic void saveCustomer(Customer customer) {HibernateUtil.getCurrentSession().save(customer);}@Overridepublic List<Customer> findAllCustomer() {return HibernateUtil.getCurrentSession().createQuery("from Customer").list();}@Overridepublic void removeCustomer(Customer customer) {HibernateUtil.getCurrentSession().delete(customer);}@Overridepublic Customer findCustomerById(Long custId) {return HibernateUtil.getCurrentSession().get(Customer.class,custId);}@Overridepublic void updateCustomer(Customer customer) {HibernateUtil.getCurrentSession().update(customer);}}

5、编写Service层代码

package cn.itcast.service;import java.util.List;import cn.itcast.domain.Customer;/** * 客户的业务层接口 * */public interface ICustomerService {/** * 保存客户 * @param customer */void saveCustomer(Customer customer);/** * 查询所有客户 * @return */List<Customer> findAllCustomer();/** * 删除客户 * @param customer */void removeCustomer(Customer customer);/** * 根据id查询客户 * @param custId * @return */Customer findCustomerById(Long custId);/** * 修改客户 * @param customer */void updateCustomer(Customer customer);//void test();}

(1)、没有用到动态代理之前的servcie层实现类

package cn.itcast.service.impl;import java.util.List;import org.hibernate.Session;import org.hibernate.Transaction;import cn.itcast.dao.ICustomerDao;import cn.itcast.dao.impl.CustomerDaoImpl;import cn.itcast.domain.Customer;import cn.itcast.service.ICustomerService;import cn.itcast.utils.HibernateUtil;/** * 客户的业务层实现类 * 事务必须在此控制 * 业务层都是调用持久层的方法 */public class CustomerServiceImpl_OLD implements ICustomerService {private ICustomerDao customerDao = new CustomerDaoImpl();@Overridepublic void saveCustomer(Customer customer) {Session s = null;Transaction tx = null;try{s = HibernateUtil.getCurrentSession();tx = s.beginTransaction();customerDao.saveCustomer(customer);tx.commit();}catch(Exception e){tx.rollback();throw new RuntimeException(e);}}@Overridepublic Customer findCustomerById(Long custId) {Session s = null;Transaction tx = null;try{s = HibernateUtil.getCurrentSession();tx = s.beginTransaction();Customer c = customerDao.findCustomerById(custId);tx.commit();return c;}catch(Exception e){tx.rollback();throw new RuntimeException(e);}}@Overridepublic List<Customer> findAllCustomer() {Session s = null;Transaction tx = null;try{s = HibernateUtil.getCurrentSession();tx = s.beginTransaction();List<Customer> cs = customerDao.findAllCustomer();tx.commit();return cs;}catch(Exception e){tx.rollback();throw new RuntimeException(e);}}@Overridepublic void removeCustomer(Customer customer) {Session s = null;Transaction tx = null;try{s = HibernateUtil.getCurrentSession();tx = s.beginTransaction();customerDao.removeCustomer(customer);tx.commit();}catch(Exception e){tx.rollback();throw new RuntimeException(e);}}@Overridepublic void updateCustomer(Customer customer) {Session s = null;Transaction tx = null;try{s = HibernateUtil.getCurrentSession();tx = s.beginTransaction();customerDao.updateCustomer(customer);tx.commit();}catch(Exception e){tx.rollback();throw new RuntimeException(e);}}}

(2)、用动态代理之后的service层实现类

package cn.itcast.service.impl;import java.util.List;import org.hibernate.Session;import org.hibernate.Transaction;import cn.itcast.dao.ICustomerDao;import cn.itcast.dao.impl.CustomerDaoImpl;import cn.itcast.domain.Customer;import cn.itcast.service.ICustomerService;import cn.itcast.utils.HibernateUtil;/** * 客户的业务层实现类 * 事务必须在此控制 * 业务层都是调用持久层的方法 */public class CustomerServiceImpl implements ICustomerService {private ICustomerDao customerDao = new CustomerDaoImpl();@Overridepublic void saveCustomer(Customer customer) {customerDao.saveCustomer(customer);}@Overridepublic Customer findCustomerById(Long custId) {return customerDao.findCustomerById(custId);}@Overridepublic List<Customer> findAllCustomer() {return customerDao.findAllCustomer();}@Overridepublic void removeCustomer(Customer customer) {customerDao.removeCustomer(customer);}@Overridepublic void updateCustomer(Customer customer) {customerDao.updateCustomer(customer);}}

6、编写代理类

package cn.itcast.factory;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import cn.itcast.service.ICustomerService;import cn.itcast.service.impl.CustomerServiceImpl;import cn.itcast.utils.HibernateUtil;public class BeanFactory {public static ICustomerService getCustomerService(){//1.定义一个业务层实现类对象final ICustomerService customerService = new CustomerServiceImpl();//2.生成业务层实现类对象的代理对象ICustomerService proxyCustomerService = (ICustomerService) Proxy.newProxyInstance(customerService.getClass().getClassLoader(), customerService.getClass().getInterfaces(), new InvocationHandler() {/** * 如何代理: * 就想再执行被代理对象的任何方法时,给它加上事务的支持 */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object rtValue = null;try{//1.开启事务HibernateUtil.beginTransaction();//2.执行方法rtValue = method.invoke(customerService, args);//业务核心方法(业务层方法在执行)//3.提交事务HibernateUtil.commit();}catch(Exception e){//4.回滚事务HibernateUtil.rollback();}finally{//5.释放资源(hibernate帮我们释放了)//HibernateUtil.getCurrentSession().close();}return rtValue;}});return proxyCustomerService;}}

7、编写执行操作数据库的动作类

package cn.itcast.ui;import cn.itcast.domain.Customer;import cn.itcast.factory.BeanFactory;import cn.itcast.service.ICustomerService;import cn.itcast.service.impl.CustomerServiceImpl;public class Client {public static void main(String[] args) {ICustomerService customerService = BeanFactory.getCustomerService();Customer c = new Customer();c.setCustName("proxy_aaa");customerService.saveCustomer(c);}}


原创粉丝点击