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

一、基于接口的动态代理

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:当前执行方法的返回值
						 */
						@Override
						public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
							Object rtValue = null;
							//1.取出money
							Float 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:当前执行方法的代理对象。
					 * 
					 * 方法的返回值:
					 * 	当前执行方法的返回值
					 */
					@Override
					public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
						Object rtValue = null;
						//1.取出money
						Float 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 {

	@Override
	public void saveCustomer(Customer customer) {
		HibernateUtil.getCurrentSession().save(customer);
	}

	@Override
	public List<Customer> findAllCustomer() {
		return HibernateUtil.getCurrentSession().createQuery("from Customer").list();
	}

	@Override
	public void removeCustomer(Customer customer) {
		HibernateUtil.getCurrentSession().delete(customer);
	}
	

	@Override
	public Customer findCustomerById(Long custId) {
		return HibernateUtil.getCurrentSession().get(Customer.class,custId);
	}

	@Override
	public 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();
	
	@Override
	public 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);
		}
	}
	
	@Override
	public 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);
		}
	}

	@Override
	public 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);
		}
	}
	

	@Override
	public 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);
		}
	}


	@Override
	public 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();
	
	@Override
	public void saveCustomer(Customer customer) {
		customerDao.saveCustomer(customer);
	}
	
	@Override
	public Customer findCustomerById(Long custId) {
		return customerDao.findCustomerById(custId);
	}

	@Override
	public List<Customer> findAllCustomer() {	
		return customerDao.findAllCustomer();
	}
	

	@Override
	public void removeCustomer(Customer customer) {	
		customerDao.removeCustomer(customer);
	}


	@Override
	public 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() {
					/**
					 * 如何代理:
					 * 	就想再执行被代理对象的任何方法时,给它加上事务的支持
					 */
					@Override
					public 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);
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值