代理模式,JDK动态代理,SpringAOP来龙去脉

这里我们学习一下代理模式,JDK的动态代理,以及以JDK为基础的springAOP实现
代理模式:类结构的模式,优点就是不需要更改原有类(被代理类)就能增强原有类(被代理类)的功能,缺点就是必须实现原有类(被代理类)的接口
JDK的动态代理:优点就是不必“复制”原有类(被代理类)接口实现类,缺点就是必须为每个被代理类实现几乎一样的方法
springAOP:优点就是采用springIOC,JDK动态代理等技术来实现AOP机制
我们展示一个类的几个方法,分别采用代理模式,JDK动态代理,springAOP机制来做些额外功能
这里定义一个接口,一个实现类

package com.fruitking.proxy;

/**
* 汽车服务类接口
* @author fruitking
* @since 2010-02-23
*/
public interface CarService {

/**
* 启动汽车
*/
public void start();

/**
* 获得汽车搭载人数
* @return
*/
public int getLoadAmount();

/**
* 设置驾驶员
* @param driver
* @return
*/
public String setDriver(String driver);

/**
* 搭载货物
* @param goods
* @throws NullPointerException
* @throws IllegalArgumentException
*/
public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException;
}



package com.fruitking.proxy;

/**
* 汽车服务类接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceImpl implements CarService{

/**
* 启动汽车
*/
public void start(){
System.out.println("start my car...");
}

/**
* 获得汽车搭载人数
* @return
*/
public int getLoadAmount(){
System.out.println("count the person amount in my car...");
return 5;
}

/**
* 设置驾驶员
* @param driver
* @return
*/
public String setDriver(String driver){
System.out.println("driver is:"+driver);
if(driver==null||"".equals(driver)){
return "There is not driver.";
}else{
return "The driver's name is " + driver + ".";
}
}

/**
* 搭载货物
* @param goods
* @throws NullPointerException
* @throws IllegalArgumentException
*/
public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{
if(goods==null||"".equals(goods)){
throw new NullPointerException("The argument goods is null.");
}else if("tiger".equals(goods)){
throw new IllegalArgumentException("The argument goods is invalid.");
}
System.out.println("load goods is:"+goods);
}
}

先来看看代理模式,定义一个代理类,然后调用代理类

package com.fruitking.proxy.pattern;

import com.fruitking.proxy.CarService;

/**
* 汽车服务类接口的代理类实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceProxy implements CarService {

private CarService carServiceTarget;//被代理的目标类

/**
* 在构造函数中设置被代理的目标类
* 也可以使用set方法设置被代理的目标类
* @param carServiceTarget
*/
public CarServiceProxy(CarService carServiceTarget){
this.carServiceTarget = carServiceTarget;
}

/**
* 启动汽车
*/
public void start(){
System.out.println("before excute target object...");
carServiceTarget.start();
System.out.println("after excute target object...");
}

/**
* 获得汽车搭载人数
* @return
*/
public int getLoadAmount(){
System.out.println("before excute target object...");
int amount = carServiceTarget.getLoadAmount();
System.out.println("after excute target object...");
return amount;
}

/**
* 设置驾驶员
* @param driver
* @return
*/
public String setDriver(String driver){
System.out.println("before excute target object...");
String resultObject = carServiceTarget.setDriver(driver);
System.out.println("after excute target object...");
return resultObject;
}

/**
* 搭载货物
* @param goods
* @throws NullPointerException
* @throws IllegalArgumentException
*/
public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{
//这里不实现任何操作
}
}



package com.fruitking.proxy.pattern;

import com.fruitking.proxy.CarService;
import com.fruitking.proxy.CarServiceImpl;

public class TestProxyPattern {

/**
* 代理模式中的调用
* @param args
*/
public static void main(String[] args) {
CarService carServiceTarget = new CarServiceImpl();
CarServiceProxy carServiceProxy = new CarServiceProxy(carServiceTarget);
//执行代理类的方法
//作用一:间接执行被代理类的方法,
//作用二:代理类可以在被代理类方法执行前后做一些额外操作
//总结:不更改原有类的功能和程序代码情况下,实现额外的功能能
//缺点:要为每个被代理类编写一个代理类,且需要实现相同接口的所有方法
carServiceProxy.start();
carServiceProxy.getLoadAmount();
String driver = carServiceProxy.setDriver("fruitking");
System.out.println(driver);
}
}



再来看看JDK动态代理

package com.fruitking.proxy.jdkdproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import com.fruitking.proxy.CarService;

/**
* java动态代理实现类
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceJDKDynamicProxy implements InvocationHandler {

private CarService carServiceTarget;//被代理的目标类

/**
* 在构造函数中设置被代理的目标类
* 也可以使用set方法设置被代理的目标类
* @param carServiceTarget
*/
public CarServiceJDKDynamicProxy(CarService carServiceTarget){
this.carServiceTarget = carServiceTarget;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before excute target object...");
Object object = method.invoke(this.carServiceTarget,args);
System.out.println("after excute target object...");
return object;
}
}



package com.fruitking.proxy.jdkdproxy;

import java.lang.reflect.Proxy;

import com.fruitking.proxy.CarService;
import com.fruitking.proxy.CarServiceImpl;

public class TestJDKDynamicProxy {

/**
* JDK中动态代理技术中的代理调用
* @param args
*/
public static void main(String[] args) {
CarService carServiceTarget = new CarServiceImpl();
CarServiceJDKDynamicProxy carServiceJDKDynamicProxyTarget = new CarServiceJDKDynamicProxy(carServiceTarget);
CarService carServiceProxy = (CarService)Proxy.newProxyInstance(carServiceTarget.getClass().getClassLoader(),new Class[]{CarService.class}, carServiceJDKDynamicProxyTarget);
//执行代理类的方法
//作用一:间接执行被代理类的方法,
//作用二:代理类可以在被代理类方法执行前后做一些额外操作
//总结:不更改原有类的功能和程序代码情况下,实现额外的功能能
//缺点:要为每个被代理类编写一个代理类,且具有相同的接口
carServiceProxy.start();
carServiceProxy.getLoadAmount();
String driver = carServiceProxy.setDriver("fruitking");
System.out.println(driver);
}

}


最后来看看spring的AOP机制的实现

package com.fruitking.proxy.springaop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceBeforeAdvice implements MethodBeforeAdvice{

public void before(Method method, Object[] args, Object target)throws Throwable {
System.out.println("before excute target object...");
String methodName = method.getName(); //得到方法名
String targetClassName = target.getClass().getName();//得到调用类名
System.out.println(targetClassName+"."+methodName+"()");
}
}


package com.fruitking.proxy.springaop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceAfterAdvice implements AfterReturningAdvice {

public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable{
String methodName = method.getName(); //得到方法名
String targetClassName = target.getClass().getName();//得到调用类名
System.out.println(targetClassName+"."+methodName+"()");
System.out.println("after excute target object...");
}
}


package com.fruitking.proxy.springaop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceAroundAdvice implements MethodInterceptor {

public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before around excute target object...");
String methodName = invocation.getMethod().getName(); //得到方法名
String targetClassName = invocation.getClass().getName();//得到调用类名
System.out.println(targetClassName+"."+methodName+"()");
Object result = invocation.proceed(); //调用横切点,即真实操作
System.out.println("after around excute target object...");
return result;
}
}


package com.fruitking.proxy.springaop;

import org.springframework.aop.ThrowsAdvice;

/**
* 使用spring的AOP机制的事前通知接口实现
* @author fruitking
* @since 2010-02-23
*/
public class CarServiceThrowsAdvice implements ThrowsAdvice {

public void afterThrowing(NullPointerException e){//可以定义多个方法,只要传入的参数是不同异常
System.out.print("not load anything goods!");
}

public void afterThrowing(IllegalArgumentException e){//可以定义多个方法,只要传入的参数是不同异常
System.out.print("load a tiger,it's very much dangerous!");
}

}

spring的配置文件,把这些使用IOC处理

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>

<bean id="carServiceTarget" class="com.fruitking.proxy.CarServiceImpl"/>

<bean id="carServiceBeforeAdvice" class="com.fruitking.proxy.springaop.CarServiceBeforeAdvice"/>

<bean id="carServiceAfterAdvice" class="com.fruitking.proxy.springaop.CarServiceAfterAdvice"/>

<bean id="carServiceAroundAdvice" class="com.fruitking.proxy.springaop.CarServiceAroundAdvice"/>

<bean id="carServiceThrowsAdvice" class="com.fruitking.proxy.springaop.CarServiceThrowsAdvice"/>

<bean id="carService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.fruitking.proxy.CarService"/>
<property name="target" ref="carServiceTarget"/>
<property name="interceptorNames">
<list>
<value>carServiceBeforeAdvice</value>
<value>carServiceAfterAdvice</value>
<value>carServiceAroundAdvice</value>
<value>carServiceThrowsAdvice</value>
</list>
</property>
</bean>

</beans>


package com.fruitking.proxy.springaop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.fruitking.proxy.CarService;

public class TestSpringAOP {

/**
* 利用spring的AOP机制实现“代理”的横向抽取机制方式
* @param args
*/
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
CarService carService = (CarService) ctx.getBean("carService");
carService.start();
carService.getLoadAmount();
String driver = carService.setDriver("fruitking");
System.out.println(driver);
System.out.println("------------------------------");
carService.loadGoods("Miss Mary");
System.out.println("------------------------------");
try{
carService.loadGoods(null);
}catch(NullPointerException e){
e.printStackTrace();
}
System.out.println("------------------------------");
try{
carService.loadGoods("tiger");
}catch(IllegalArgumentException e){
e.printStackTrace();
}
}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值