总结结构:
静态代理模式的缺点:
1、如果一个系统中有100Dao,则创建100个代理对象
2、如果一个dao中有很多方法需要事务,则代理对象的方法中重复代码还是很多
3、由第一点和第二点可以得出:proxy的重用性不强
因为静态代理无法满足开发需求所以 引出动态代理
动态代理模式:
1、产生的代理对象和目标对象实现了共同的接口
jdk动态代理
2、代理对象是目标对象的子类
hibernate: Person person = session.load(Person.class,1L); javassisit
spring:cglib动态代理
jdk的动态代理:
1、因为是用jdk的API做到的
2、代理对象是动态产生的
cglib产生的代理类是目标类的子类
注意事项:
1、拦截器中invoke方法体的内容就是代理对象方法体的内容
2、当客户端执行代理对象.方法时,进入到了拦截器的invoke方法体
3、拦截器中invoke方法的method参数是在调用的时候赋值的
aop:
1、切面
事务、日志、安全性框架、权限等都是切面
2、通知
切面中的方法就是通知
3、目标类
4、切入点
只有符合切入点,才能让通知和目标方法结合在一起
5、织入:
形成代理对象的方法的过程
好处:
事务、日志、安全性框架、权限、目标方法之间完全是松耦合的
jdk的动态代理举例
PersonDao.java
1 package cn.itcast.jdkproxy.sh; 2 3 public interface PersonDao { 4 public void savePerson(); 5 public void updatePerson(); 6 public void deletePerson(); 7 }
PersonDaoImpl.java
1 package cn.itcast.jdkproxy.sh; 2 3 public class PersonDaoImpl implements PersonDao{ 4 public void deletePerson() { 5 System.out.println("delete person"); 6 } 7 public void savePerson() { 8 System.out.println("save person"); 9 } 10 public void updatePerson() { 11 System.out.println("update person"); 12 } 13 }
Transaction.java
1 package cn.itcast.jdkproxy.sh; 2 3 public class Transaction { 4 public void beginTransaction(){ 5 System.out.println("开启事务 "); 6 } 7 public void commit(){ 8 System.out.println("事务提交"); 9 } 10 }
PersonInterceptor.java
1 package cn.itcast.jdkproxy.sh; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 /** 7 * 拦截器 8 * @author Think 9 * 1、引入目标类 10 * 2、引入事务 11 * 3、通过构造函数给目标类和事务赋值 12 * 4、填充invoke方法 13 * 14 */ 15 public class PersonInterceptor implements InvocationHandler{ 16 17 private Object target;//目标类 18 private Transaction transaction;//引入事务 19 20 public PersonInterceptor(Object target,Transaction transaction){ 21 this.target = target; 22 this.transaction = transaction; 23 } 24 25 26 @Override 27 public Object invoke(Object proxy, Method method, Object[] args) 28 throws Throwable { 29 // TODO Auto-generated method stub 30 this.transaction.beginTransaction(); 31 method.invoke(this.target, args);//调用目标类的方法 32 this.transaction.commit(); 33 return null; 34 } 35 36 }
ProxyTest.java
1 package cn.itcast.jdkproxy.sh; 2 3 import java.lang.reflect.Proxy; 4 5 import org.junit.Test; 6 import org.springframework.context.ApplicationContext; 7 import org.springframework.context.support.ClassPathXmlApplicationContext; 8 9 public class ProxyTest { 10 @Test 11 public void test(){ 12 Object target = new PersonDaoImpl(); 13 Transaction transaction = new Transaction(); 14 PersonInterceptor interceptor = new PersonInterceptor(target, transaction); 15 /** 16 * 1、目标类的类加载器 17 * 2、目标类实现的所有的接口 18 * 3、拦截器 19 */ 20 PersonDao personDao = (PersonDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor); 21 personDao.deletePerson(); 22 } 23 }
实现jdk的动态代理,以上例子的改进可以在PersonInterceptor.java中添加成员函数
private List<Interceptor> interceptors;
然后让切面都继承 Interceptor接口,这个接口是自己定义的。
改进版例子:
1 package cn.itcast.jdkproxy.salary; 2 3 public interface Interceptor { 4 public void interceptor(); 5 }
其它类:很多
1 package cn.itcast.jdkproxy.salary; 2 3 public class Logger implements Interceptor{ 4 5 @Override 6 public void interceptor() { 7 // TODO Auto-generated method stub 8 System.out.println("logging"); 9 } 10 11 }
1 package cn.itcast.jdkproxy.salary; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.util.List; 6 7 public class SalaryInterceptor implements InvocationHandler{ 8 9 10 private Object target; 11 12 private List<Interceptor> interceptors; 13 14 public SalaryInterceptor(Object target,List<Interceptor> interceptors){ 15 this.target = target; 16 this.interceptors = interceptors; 17 } 18 19 @Override 20 public Object invoke(Object proxy, Method method, Object[] args) 21 throws Throwable { 22 for(Interceptor interceptor:interceptors){ 23 interceptor.interceptor(); 24 } 25 method.invoke(this.target, args); 26 return null; 27 } 28 29 }
客户端测试类
1 package cn.itcast.jdkproxy.salary; 2 3 import java.lang.reflect.Proxy; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import org.junit.Test; 8 9 public class SalaryTest { 10 @Test 11 public void test(){ 12 Object target = new SalaryManagerImpl(); 13 Logger logger = new Logger(); 14 Security security = new Security(); 15 Privilege privilege = new Privilege(); 16 List<Interceptor> interceptors = new ArrayList<Interceptor>(); 17 interceptors.add(logger); 18 interceptors.add(security); 19 interceptors.add(privilege); 20 SalaryInterceptor interceptor = new SalaryInterceptor(target, interceptors); 21 SalaryManager salaryManager = (SalaryManager)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor); 22 salaryManager.showSalary(); 23 } 24 }