一、基于接口的动态代理
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);
}
}