Proxy模式的功能有很多,比如远程代理,用来给远程对象提供一个本地代表;虚代理,用来为创建开大开销的对象提供缓冲,等等。
今天以权限控制为例简单讲讲代理模式。
实现代理模式三种方式:
1、静态代理
2、动态代理
3、Spring中的AOP
1.静态代理
代理从接口出发,这里有个业务组件接口:
package proxy.ttcp;
public interface ICompent{
public void bus1() ;
public void bus2() ;
public void bus3() ;
}
编写代理对象,代理对象实现被代理接口:
package proxy.ttcp;
public class ProxyCompent implements ICompent{
private ICompent compent;
public ProxyCompent (ICompent compent){
this.compent = compent;
}
public void check(){
System.out.println("权限控制。。。") ;
}
public void bus1(){
check() ;
compent.bus1() ;
}
public void bus2(){
check() ;
ccompent.bus2() ;
}
public void bus3(){
check() ;
compent.bus3() ;
}
}
编写被代理对象,实现被代理接口:
package proxy.ttcp;
public class Compent implements ICompent{
public void bus1() {
// TODO Auto-generated method stub
System.out.println("ttcp1") ;
}
public void bus2() {
// TODO Auto-generated method stub
System.out.println("ttcp2") ;
}
public void bus3() {
// TODO Auto-generated method stub
System.out.println("ttcp3") ;
}
}
写一个测试类:
package proxy.ttcp;
public class Test{
public static void main(String []args){
ICompent proxy = new Proxy(new Compent()) ;
proxy.bus1() ;
proxy.bus2() ;
proxy.bus3() ;
}
}
这就是静态代理,但是程序规模很大时就胜任不了,接下来便引出动态代理
2.动态代理
结合静态代理的实现机制,抽象出一个泛类代理,也就是说不依赖任何被代理对象的代理实现
设计一个处理被代理对象的类,该类实现InvocationHandler接口:
package dynaProxy.ttcp;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.*;
public class DynamicProxy implements InvocationHandler {
private Object obj ;
public Object bind(Object obj){
this.obj = obj ;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this) ;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
try{
check() ;
method.invoke(obj, args) ;
}catch(Exception ex){
ex.printStackTrace() ;
}
return null;
}
public void check(){
System.out.println("验证.....") ;
}
}
使用Proxy.newProxyInstance静态方法建立一个代理对象,obj.getClass().getInterfaces()
来告知所要代理的接口,通过method.invoke(obj, args) 调用代理对象中的方法,method.invoke
返回的结果也就是代理对象中方法返回的结果。
测试类:
package dynaProxy.ttcp;
import proxy.ttcp.Compent;
import proxy.ttcp.ICompent;
public class Test {
public static void main(String []args){
DynamicProxy proxy = new DynamicProxy() ;
ICompent com = (ICompent)proxy.bind(new Compent()) ;
com.bus1() ;
com.bus2() ;
com.bus3() ;
}
}
3.AOP
以前置通知为例
被代理接口使用之前的ICompent,接口的实现也使用之前的Compent
编写前置通知,该类实现MethodBeforeAdvice
package aop.ttcp;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class AdviceBefore implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("权限验证。。。") ;
}
}
application.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans "
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance "
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd ">
<bean id="beforeAdvice" class="aop.ttcp.AdviceBefore"/>
<bean id="compent" class="proxy.ttcp.Compent"/>
<bean id="proxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 被代理类要实现的接口 -->
<property name="proxyInterfaces" value="proxy.ttcp.ICompent"/>
<!--目标对象-->
<property name="target" ref="compent"/>
<property name="interceptorNames">
<list>
<!--代理对象-->
<value>beforeAdvice</value>
</list>
</property>
</bean>
</beans>
编写测试类
package tradition.ttcp;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import proxy.ttcp.ICompent;
public class Test {
public static void main(String []args){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml") ;
ICompent compent = (ICompent)context.getBean("proxy") ;
compent.bus1() ;
compent.bus2() ;
compent.bus3() ;
}
}
可以看到与之前的静态、动态代理的结果一样
除了前置通知外,还有后置通知,环绕通知等