Spring学习笔记(17)-----------Spring AOP总结(2)

Spring中AOP的代理方式

 

 静态代理类:
    
由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的
.class文件就已经存在了。


    动态代理类在程序运行时,运用反射机制动态创建而成 。动态代理分为两种代理;

 

jdk代理和cglib的代理

jdk代理必须有一个接口用来实现,就是对目标对象生成代理,进行代理,然后就是返回目标对象的代理。Invoction

cglib和jdk代理的区别在与 他需要导入一个cglib.jar包,cglib是基于jdk封装而成的,主要的就是cglib相对灵活,因为jdk必须要实现接口

而cglib可以使接口也可以是类。

 

 

 

静态代理和动态代理

 

代理,应该就是在不破坏原有代码的基础上,对原有代码进行扩充。

一、静态代理

代理类与原类实现相同的接口。

不过静态代理会在代码里写死,对于需要在运行期生成的代码就无能为力了。

1.UserManager.java

 

package com;

public interface UserManager {

public void addUser(String username, String password);

public void deleteUser(int id);

public void modifyUser(int id, String username, String password);

public String findUserByID(int id);
}

 

2.UserManagerImpl.java

 

package com;

public class UserManagerImpl implements UserManager {

public void addUser(String username, String password) {
System.out.println("========UserManagerImpl.addUser()===================");
}

public void deleteUser(int id) {
System.out.println("========UserManagerImpl.deleteUser()===================");
}

public String findUserByID(int id) {
System.out.println("========UserManagerImpl.findUserByID()===================");
return "ok";
}

public void modifyUser(int id, String username, String password) {
System.out.println("========UserManagerImpl.modifyUser()===================");
}

}

 

3.UserManagerImplProxy.java(代理类)

 

package com;

public class UserManagerImplProxy implements UserManager {

private UserManager userManager;
public UserManagerImplProxy(UserManager userManager) {
this.userManager = userManager;
}
@Override
public void addUser(String username, String password) {
// TODO Auto-generated method stub
checkSecurity();
userManager.addUser(username, password);
}

@Override
public void deleteUser(int id) {
// TODO Auto-generated method stub
userManager.deleteUser(id);
}

@Override
public String findUserByID(int id) {
// TODO Auto-generated method stub
return userManager.findUserByID(id);
}

@Override
public void modifyUser(int id, String username, String password) {
// TODO Auto-generated method stub
userManager.modifyUser(id, username, password);
}

private void checkSecurity() {
System.out.println("==============checkSecurity()==================");
}
}

 

4.Client.java(客户端)

 

package com;

public class Client {

public static void main(String[] args) {
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
userManager.addUser("Tom", "123");
}

}

 

二、动态代理

可以解决运行期执行的问题,动态代理没有必要事先将代码写死。

1.SecurityHandler.java

 

package com;

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

public class SecurityHandler implements InvocationHandler {


private Object targetObject;


public Object newProxy(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
checkSecurity();
//方法返回值
Object ret = null;
try {
//args是方法参数
ret = method.invoke(targetObject, args);
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ret;
}

private void checkSecurity() {
System.out.println("===============checkSecurity()===================");
}
}

 

2.Client.java

 

package com;

public class Client {

public static void main(String[] args) {
SecurityHandler handler = new SecurityHandler();

UserManager userManager = (UserManager)handler.newProxy(new UserManagerImpl());
userManager.addUser("Tom", "123");
System.out.println(userManager.findUserByID(1));
}

}

 

 

 

 

动态代理的JDK代理和CGLib代理

 

JDK代理

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

Java代码
  1. package com.fruitking.proxy;  
  2.   
  3. /** 
  4.  * 汽车服务类接口 
  5.  * @author fruitking 
  6.  * @since 2010-02-23 
  7.  */  
  8. public interface CarService {  
  9.       
  10.     /** 
  11.      * 启动汽车 
  12.      */  
  13.     public void start();  
  14.       
  15.     /** 
  16.      * 获得汽车搭载人数 
  17.      * @return 
  18.      */  
  19.     public int getLoadAmount();  
  20.       
  21.     /** 
  22.      * 设置驾驶员 
  23.      * @param driver 
  24.      * @return 
  25.      */  
  26.     public String setDriver(String driver);  
  27.       
  28.     /** 
  29.      * 搭载货物 
  30.      * @param goods 
  31.      * @throws NullPointerException 
  32.      * @throws IllegalArgumentException 
  33.      */  
  34.     public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException;  
  35. }  



 

Java代码
  1. package com.fruitking.proxy;  
  2.   
  3. /** 
  4.  * 汽车服务类接口实现 
  5.  * @author fruitking 
  6.  * @since 2010-02-23 
  7.  */  
  8. public class CarServiceImpl implements CarService{  
  9.       
  10.     /** 
  11.      * 启动汽车 
  12.      */  
  13.     public void start(){  
  14.         System.out.println("start my car...");  
  15.     }  
  16.       
  17.     /** 
  18.      * 获得汽车搭载人数 
  19.      * @return 
  20.      */  
  21.     public int getLoadAmount(){  
  22.         System.out.println("count the person amount in my car...");  
  23.         return 5;  
  24.     }  
  25.       
  26.     /** 
  27.      * 设置驾驶员 
  28.      * @param driver 
  29.      * @return 
  30.      */  
  31.     public String setDriver(String driver){  
  32.         System.out.println("driver is:"+driver);  
  33.         if(driver==null||"".equals(driver)){  
  34.             return "There is not driver.";  
  35.         }else{  
  36.             return "The driver's name is " + driver + ".";  
  37.         }  
  38.     }  
  39.       
  40.     /** 
  41.      * 搭载货物 
  42.      * @param goods 
  43.      * @throws NullPointerException 
  44.      * @throws IllegalArgumentException 
  45.      */  
  46.     public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{  
  47.         if(goods==null||"".equals(goods)){  
  48.             throw new NullPointerException("The argument goods is null.");  
  49.         }else if("tiger".equals(goods)){  
  50.             throw new IllegalArgumentException("The argument goods is invalid.");  
  51.         }  
  52.         System.out.println("load goods is:"+goods);  
  53.     }  
  54. }  


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

Java代码
  1. package com.fruitking.proxy.pattern;  
  2.   
  3. import com.fruitking.proxy.CarService;  
  4.   
  5. /** 
  6.  * 汽车服务类接口的代理类实现 
  7.  * @author fruitking 
  8.  * @since 2010-02-23 
  9.  */  
  10. public class CarServiceProxy implements CarService {  
  11.       
  12.     private CarService carServiceTarget;//被代理的目标类  
  13.       
  14.     /** 
  15.      * 在构造函数中设置被代理的目标类 
  16.      * 也可以使用set方法设置被代理的目标类 
  17.      * @param carServiceTarget 
  18.      */  
  19.     public CarServiceProxy(CarService carServiceTarget){  
  20.         this.carServiceTarget = carServiceTarget;  
  21.     }  
  22.   
  23.     /** 
  24.      * 启动汽车 
  25.      */  
  26.     public void start(){  
  27.         System.out.println("before excute target object...");  
  28.         carServiceTarget.start();  
  29.         System.out.println("after excute target object...");  
  30.     }  
  31.       
  32.     /** 
  33.      * 获得汽车搭载人数 
  34.      * @return 
  35.      */  
  36.     public int getLoadAmount(){  
  37.         System.out.println("before excute target object...");  
  38.         int amount = carServiceTarget.getLoadAmount();  
  39.         System.out.println("after excute target object...");  
  40.         return amount;  
  41.     }  
  42.       
  43.     /** 
  44.      * 设置驾驶员 
  45.      * @param driver 
  46.      * @return 
  47.      */  
  48.     public String setDriver(String driver){  
  49.         System.out.println("before excute target object...");  
  50.         String resultObject = carServiceTarget.setDriver(driver);  
  51.         System.out.println("after excute target object...");  
  52.         return resultObject;  
  53.     }  
  54.       
  55.     /** 
  56.      * 搭载货物 
  57.      * @param goods 
  58.      * @throws NullPointerException 
  59.      * @throws IllegalArgumentException 
  60.      */  
  61.     public void loadGoods(String goods)throws NullPointerException,IllegalArgumentException{  
  62.         //这里不实现任何操作  
  63.     }  
  64. }  



 

Java代码
  1. package com.fruitking.proxy.pattern;  
  2.   
  3. import com.fruitking.proxy.CarService;  
  4. import com.fruitking.proxy.CarServiceImpl;  
  5.   
  6. public class TestProxyPattern {  
  7.   
  8.     /** 
  9.      * 代理模式中的调用 
  10.      * @param args 
  11.      */  
  12.     public static void main(String[] args) {  
  13.         CarService carServiceTarget = new CarServiceImpl();  
  14.         CarServiceProxy carServiceProxy = new CarServiceProxy(carServiceTarget);  
  15.         //执行代理类的方法  
  16.         //作用一:间接执行被代理类的方法,  
  17.         //作用二:代理类可以在被代理类方法执行前后做一些额外操作  
  18.         //总结:不更改原有类的功能和程序代码情况下,实现额外的功能能  
  19.         //缺点:要为每个被代理类编写一个代理类,且需要实现相同接口的所有方法  
  20.         carServiceProxy.start();  
  21.         carServiceProxy.getLoadAmount();  
  22.         String driver = carServiceProxy.setDriver("fruitking");  
  23.         System.out.println(driver);  
  24.     }  
  25. }  



再来看看JDK动态代理

Java代码
  1. package com.fruitking.proxy.jdkdproxy;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5.   
  6. import com.fruitking.proxy.CarService;  
  7.   
  8. /** 
  9.  * java动态代理实现类 
  10.  * @author fruitking 
  11.  * @since 2010-02-23 
  12.  */  
  13. public class CarServiceJDKDynamicProxy implements InvocationHandler {  
  14.   
  15.     private CarService carServiceTarget;//被代理的目标类  
  16.       
  17.     /** 
  18.      * 在构造函数中设置被代理的目标类 
  19.      * 也可以使用set方法设置被代理的目标类 
  20.      * @param carServiceTarget 
  21.      */  
  22.     public CarServiceJDKDynamicProxy(CarService carServiceTarget){  
  23.         this.carServiceTarget = carServiceTarget;  
  24.     }  
  25.       
  26.     public Object invoke(Object proxy, Method method, Object[] args)  
  27.             throws Throwable {  
  28.         System.out.println("before excute target object...");  
  29.         Object object = method.invoke(this.carServiceTarget,args);  
  30.         System.out.println("after excute target object...");  
  31.         return object;  
  32.     }  
  33. }  



 

Java代码
  1. package com.fruitking.proxy.jdkdproxy;  
  2.   
  3. import java.lang.reflect.Proxy;  
  4.   
  5. import com.fruitking.proxy.CarService;  
  6. import com.fruitking.proxy.CarServiceImpl;  
  7.   
  8. public class TestJDKDynamicProxy {  
  9.   
  10.     /** 
  11.      * JDK中动态代理技术中的代理调用 
  12.      * @param args 
  13.      */  
  14.     public static void main(String[] args) {  
  15.         CarService carServiceTarget = new CarServiceImpl();  
  16.         CarServiceJDKDynamicProxy carServiceJDKDynamicProxyTarget = new CarServiceJDKDynamicProxy(carServiceTarget);  
  17.         CarService carServiceProxy = (CarService)Proxy.newProxyInstance(carServiceTarget.getClass().getClassLoader(),new Class[]{CarService.class}, carServiceJDKDynamicProxyTarget);  
  18.         //执行代理类的方法  
  19.         //作用一:间接执行被代理类的方法,  
  20.         //作用二:代理类可以在被代理类方法执行前后做一些额外操作  
  21.         //总结:不更改原有类的功能和程序代码情况下,实现额外的功能能  
  22.         //缺点:要为每个被代理类编写一个代理类,且具有相同的接口  
  23.         carServiceProxy.start();  
  24.         carServiceProxy.getLoadAmount();  
  25.         String driver = carServiceProxy.setDriver("fruitking");  
  26.         System.out.println(driver);  
  27.     }  
  28.   
  29. }  



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

Java代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import org.springframework.aop.MethodBeforeAdvice;  
  6.   
  7. /** 
  8.  * 使用spring的AOP机制的事前通知接口实现 
  9.  * @author fruitking 
  10.  * @since 2010-02-23 
  11.  */  
  12. public class CarServiceBeforeAdvice implements MethodBeforeAdvice{  
  13.       
  14.     public void before(Method method, Object[] args, Object target)throws Throwable {  
  15.         System.out.println("before excute target object...");  
  16.         String methodName = method.getName();  //得到方法名   
  17.         String targetClassName = target.getClass().getName();//得到调用类名  
  18.         System.out.println(targetClassName+"."+methodName+"()");  
  19.     }  
  20. }  


 

Java代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import org.springframework.aop.AfterReturningAdvice;  
  6.   
  7. /** 
  8.  * 使用spring的AOP机制的事前通知接口实现 
  9.  * @author fruitking 
  10.  * @since 2010-02-23 
  11.  */  
  12. public class CarServiceAfterAdvice implements AfterReturningAdvice {  
  13.   
  14.     public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable{  
  15.         String methodName = method.getName();  //得到方法名   
  16.         String targetClassName = target.getClass().getName();//得到调用类名  
  17.         System.out.println(targetClassName+"."+methodName+"()");  
  18.         System.out.println("after excute target object...");  
  19.     }  
  20. }  


 

Java代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import org.aopalliance.intercept.MethodInterceptor;  
  4. import org.aopalliance.intercept.MethodInvocation;  
  5.   
  6. /** 
  7.  * 使用spring的AOP机制的事前通知接口实现 
  8.  * @author fruitking 
  9.  * @since 2010-02-23 
  10.  */  
  11. public class CarServiceAroundAdvice implements MethodInterceptor {  
  12.       
  13.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  14.         System.out.println("before around excute target object...");  
  15.         String methodName = invocation.getMethod().getName();  //得到方法名   
  16.         String targetClassName = invocation.getClass().getName();//得到调用类名  
  17.         System.out.println(targetClassName+"."+methodName+"()");  
  18.         Object result = invocation.proceed(); //调用横切点,即真实操作  
  19.         System.out.println("after around excute target object...");  
  20.         return result;  
  21.     }  
  22. }  


 

Java代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import org.springframework.aop.ThrowsAdvice;  
  4.   
  5. /** 
  6.  * 使用spring的AOP机制的事前通知接口实现 
  7.  * @author fruitking 
  8.  * @since 2010-02-23 
  9.  */  
  10. public class CarServiceThrowsAdvice implements ThrowsAdvice {  
  11.       
  12.     public void afterThrowing(NullPointerException e){//可以定义多个方法,只要传入的参数是不同异常  
  13.         System.out.print("not load anything goods!");  
  14.     }  
  15.       
  16.     public void afterThrowing(IllegalArgumentException e){//可以定义多个方法,只要传入的参数是不同异常  
  17.         System.out.print("load a tiger,it's very much dangerous!");  
  18.     }  
  19.   
  20. }  


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

Java代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">  
  3. <beans>  
  4.       
  5.     <bean id="carServiceTarget" class="com.fruitking.proxy.CarServiceImpl"/>  
  6.        
  7.     <bean id="carServiceBeforeAdvice" class="com.fruitking.proxy.springaop.CarServiceBeforeAdvice"/>  
  8.       
  9.     <bean id="carServiceAfterAdvice" class="com.fruitking.proxy.springaop.CarServiceAfterAdvice"/>  
  10.       
  11.     <bean id="carServiceAroundAdvice" class="com.fruitking.proxy.springaop.CarServiceAroundAdvice"/>  
  12.       
  13.     <bean id="carServiceThrowsAdvice" class="com.fruitking.proxy.springaop.CarServiceThrowsAdvice"/>  
  14.       
  15.     <bean id="carService" class="org.springframework.aop.framework.ProxyFactoryBean">   
  16.         <property name="proxyInterfaces" value="com.fruitking.proxy.CarService"/>   
  17.         <property name="target" ref="carServiceTarget"/>   
  18.         <property name="interceptorNames">   
  19.             <list>   
  20.                 <value>carServiceBeforeAdvice</value>  
  21.                 <value>carServiceAfterAdvice</value>  
  22.                 <value>carServiceAroundAdvice</value>  
  23.                 <value>carServiceThrowsAdvice</value>  
  24.             </list>   
  25.         </property>  
  26.     </bean>  
  27.       
  28. </beans>  


 

Java代码
  1. package com.fruitking.proxy.springaop;  
  2.   
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. import com.fruitking.proxy.CarService;  
  7.   
  8. public class TestSpringAOP {  
  9.   
  10.     /** 
  11.      * 利用spring的AOP机制实现“代理”的横向抽取机制方式 
  12.      * @param args 
  13.      */  
  14.     public static void main(String[] args) {  
  15.         ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");   
  16.         CarService carService = (CarService) ctx.getBean("carService");  
  17.         carService.start();  
  18.         carService.getLoadAmount();  
  19.         String driver = carService.setDriver("fruitking");  
  20.         System.out.println(driver);  
  21.         System.out.println("------------------------------");  
  22.         carService.loadGoods("Miss Mary");  
  23.         System.out.println("------------------------------");  
  24.         try{  
  25.             carService.loadGoods(null);  
  26.         }catch(NullPointerException e){  
  27.             e.printStackTrace();  
  28.         }  
  29.         System.out.println("------------------------------");  
  30.         try{  
  31.             carService.loadGoods("tiger");  
  32.         }catch(IllegalArgumentException e){  
  33.             e.printStackTrace();  
  34.         }  
  35.     }  
  36.   
  37. }  

 

CGlib代理

 

Java代码
  1. package com.bjsxt.spring;   
  2.   
  3. public class UserManagerImpl {   
  4.        
  5.        
  6.     public void addUser(String name, String password) {   
  7.         System.out.println("UserManagerImpl.addUser() -- name: " + name);   
  8.     }   
  9.   
  10.     public void delUser(int id) {   
  11.         System.out.println("UserManagerImpl.delUser() -- id: " + id);   
  12.     }   
  13.   
  14.     public void modifyUser(int id, String name, String password) {   
  15.         System.out.println("UserManagerImpl.modifyUser() -- id: " + id);   
  16.     }   
  17.   
  18. }  
package com.bjsxt.spring; public class UserManagerImpl { public void addUser(String name, String password) { System.out.println("UserManagerImpl.addUser() -- name: " + name); } public void delUser(int id) { System.out.println("UserManagerImpl.delUser() -- id: " + id); } public void modifyUser(int id, String name, String password) { System.out.println("UserManagerImpl.modifyUser() -- id: " + id); } }

 

 

 

Java代码
  1. package com.bjsxt.spring;   
  2.   
  3. import org.aspectj.lang.JoinPoint;   
  4.   
  5. public class MySecurityManagerImpl {   
  6.        
  7.     public void checkSecurity(JoinPoint joinPoint) {   
  8.         Object[] args = joinPoint.getArgs();   
  9.         if (args != null) {   
  10.             for (int i = 0; i < args.length; i++) {   
  11.                 System.out.println(args[i]);   
  12.             }   
  13.         if ("张三".equals(args[0])) {   
  14.             System.out.println("你没有权限访问");   
  15.         }   
  16.         }   
  17.         //...    
  18.         //...   
  19.         //System.out.println("进行安全检查!!");   
  20.     }   
  21. }  
package com.bjsxt.spring; import org.aspectj.lang.JoinPoint; public class MySecurityManagerImpl { public void checkSecurity(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); if (args != null) { for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } if ("张三".equals(args[0])) { System.out.println("你没有权限访问");
                }
               

 

 

2.看看这次spring配置文件是如何配置的.

 

Xml代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <!--   
  4.   - Application context definition for JPetStore's business layer.   
  5.   - Contains bean references to the transaction manager and to the DAOs in   
  6.   - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").   
  7.   -->  
  8. <beans xmlns="http://www.springframework.org/schema/beans"  
  9.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  10.          xmlns:aop="http://www.springframework.org/schema/aop"  
  11.          xmlns:tx="http://www.springframework.org/schema/tx"  
  12.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  13.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd   
  14.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
  15.        
  16.     <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/>  
  17.        
  18.     <bean id="mySecurityManager" class="com.bjsxt.spring.MySecurityManagerImpl"/>  
  19.        
  20.     <aop:config>  
  21.         <aop:pointcut id="allAddMethod" expression="execution(* add*(..))"/>  
  22.         <aop:aspect id="securityAspect" ref="mySecurityManager">  
  23.             <aop:before pointcut-ref="allAddMethod" method="checkSecurity"/>  
  24.         </aop:aspect>        
  25.     </aop:config>  
  26.            
  27. </beans>  
<?xml version="1.0" encoding="UTF-8"?> <!-- - Application context definition for JPetStore's business layer. - Contains bean references to the transaction manager and to the DAOs in - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation"). --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/> <bean id="mySecurityManager" class="com.bjsxt.spring.MySecurityManagerImpl"/> <aop:config> <aop:pointcut id="allAddMethod" expression="execution(* add*(..))"/> <aop:aspect id="securityAspect" ref="mySecurityManager"> <aop:before pointcut-ref="allAddMethod" method="checkSecurity"/> </aop:aspect> </aop:config> </beans>

 

 

 

3.写测试类

 

Java代码
  1. package com.bjsxt.spring;   
  2.   
  3. import org.springframework.beans.factory.BeanFactory;   
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  5.   
  6. import junit.framework.TestCase;   
  7.   
  8.   
  9. public class TestAop extends TestCase {   
  10.        
  11.     public void testAop1() {   
  12.         //读取配置文件,获取BeanFactory   
  13.         BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext-beans.xml");   
  14.         UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");   
  15.         userManager.addUser("张三""123");   
  16. //      userManager.delUser(1);   
  17. //      userManager.modifyUser(1, "李四", "abc");   
  18.     }   
  19. }  
package com.bjsxt.spring; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationC<wbr>ontext; import junit.framework.TestCase; public class TestAop extends TestCase { public void testAop1() { //读取配置文件,获取BeanFactory BeanFactory factory = new ClassPathXmlApplicationC<wbr>ontext("applicationContext-beans.xml"); UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager"); userManager.addUser("张三", "123"); // userManager.delUser(1); // userManager.modifyUser(1, "李四", "abc"); } }</wbr></wbr>

 

 

4.我们看看运行结果:

 

Java代码
  1. 张三   
  2. 123  
  3. 你没有权限访问   
  4. UserManagerImpl.addUser() -- name: 张三   
张三 123 你没有权限访问 UserManagerImpl.addUser() -- name: 张三 <wbr> </wbr>

 

 

5. 如果目标类实现了接口,默认采用JDK动态代理来实现AOP
    如果目标类没有实现接口,必须添加CGLIB支持,Spring会自动的在JDK和CGLIB代理之间切换
    如果目标类实现了接口,可以定义让spring强制使用CGLIB代理

    如何强制使用CGLIB代理实现AOP
    将<aop:config>定义为<aop:config proxy-target-class="true">,
    并且要引入CGLIB包:SPRING_HOME\lib\cglib\*.jar

 

JDK和CGLib的区别:

 

spring对AOP的支持

*如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
* 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
*如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换


如何强制使用CGLIB实现AOP?
 * 添加CGLIB库,SPRING_HOME/cglib/*.jar
 * 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
 
JDK动态代理和CGLIB字节码生成的区别?
 * JDK动态代理只能对实现了接口的类生成代理,而不能针对类
 * CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
   因为是继承,所以该类或方法最好不要声明成final 

 

实例解析:

UserManager接口

[java] view plain copy print ?
  1. package com.macower.spring.proxy;  
  2.   
  3. public interface UserManager {  
  4.     public void addUser(String id, String password);  
  5.     public void delUser(String id);  
  6. }  

package com.macower.spring.proxy; public interface UserManager { public void addUser(String id, String password); public void delUser(String id); }

接下来是其实现类  UserManagerImpl

 

[java] view plain copy print ?
  1. package com.macower.spring.proxy;  
  2.   
  3. public class UserManagerImpl implements UserManager {  
  4.   
  5.     public void addUser(String id, String password) {  
  6.         System.out.println(".: 掉用了UserManagerImpl.addUser()方法! ");  
  7.   
  8.     }  
  9.   
  10.     public void delUser(String id) {  
  11.         System.out.println(".: 掉用了UserManagerImpl.delUser()方法! ");  
  12.   
  13.     }  
  14. }  

package com.macower.spring.proxy; public class UserManagerImpl implements UserManager { public void addUser(String id, String password) { System.out.println(".: 掉用了UserManagerImpl.addUser()方法! "); } public void delUser(String id) { System.out.println(".: 掉用了UserManagerImpl.delUser()方法! "); } }

 

JDK动态代理类

 

[java] view plain copy print ?
  1. package com.macower.spring.proxy;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. /** 
  6.  *  
  7.  * JDK动态代理类 
  8.  * @author Macower 
  9.  * 
  10.  */  
  11. public class JDKProxy implements InvocationHandler {  
  12.   
  13.     private Object targetObject;//需要代理的目标对象  
  14.   
  15.     public Object newProxy(Object targetObject) {//将目标对象传入进行代理  
  16.         this.targetObject = targetObject;   
  17.         return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
  18.                 targetObject.getClass().getInterfaces(), this);//返回代理对象  
  19.     }  
  20.   
  21.     public Object invoke(Object proxy, Method method, Object[] args)//invoke方法  
  22.             throws Throwable {  
  23.         checkPopedom();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限  
  24.         Object ret = null;      // 设置方法的返回值  
  25.         ret  = method.invoke(targetObject, args);       //调用invoke方法,ret存储该方法的返回值  
  26.         return ret;  
  27.     }  
  28.   
  29.     private void checkPopedom() {//模拟检查权限的例子  
  30.         System.out.println(".:检查权限  checkPopedom()!");  
  31.     }  
  32. }  

package com.macower.spring.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * * JDK动态代理类 * @author Macower * */ public class JDKProxy implements InvocationHandler { private Object targetObject;//需要代理的目标对象 public Object newProxy(Object targetObject) {//将目标对象传入进行代理 this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);//返回代理对象 } public Object invoke(Object proxy, Method method, Object[] args)//invoke方法 throws Throwable { checkPopedom();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限 Object ret = null; // 设置方法的返回值 ret = method.invoke(targetObject, args); //调用invoke方法,ret存储该方法的返回值 return ret; } private void checkPopedom() {//模拟检查权限的例子 System.out.println(".:检查权限 checkPopedom()!"); } }

CGLibProxy动态代理类

 

 

[java] view plain copy print ?
  1. package com.macower.spring.proxy;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import net.sf.cglib.proxy.Enhancer;  
  6. import net.sf.cglib.proxy.MethodInterceptor;  
  7. import net.sf.cglib.proxy.MethodProxy;  
  8.   
  9. /** 
  10.  * CGLibProxy动态代理类的实例 
  11.  *  
  12.  * @author Macower 
  13.  *  
  14.  */  
  15. public class CGLibProxy implements MethodInterceptor {  
  16.   
  17.     private Object targetObject;// CGLib需要代理的目标对象  
  18.   
  19.     public Object createProxyObject(Object obj) {  
  20.         this.targetObject = obj;  
  21.         Enhancer enhancer = new Enhancer();  
  22.         enhancer.setSuperclass(obj.getClass());  
  23.         enhancer.setCallback(this);  
  24.         Object proxyObj = enhancer.create();  
  25.         return proxyObj;// 返回代理对象  
  26.     }  
  27.   
  28.     public Object intercept(Object proxy, Method method, Object[] args,  
  29.             MethodProxy methodProxy) throws Throwable {  
  30.         Object obj = null;  
  31.         if ("addUser".equals(method.getName())) {// 过滤方法  
  32.             checkPopedom();// 检查权限  
  33.         }  
  34.         obj = method.invoke(targetObject, args);  
  35.         return obj;  
  36.     }  
  37.   
  38.     private void checkPopedom() {  
  39.         System.out.println(".:检查权限  checkPopedom()!");  
  40.     }  
  41. }  

package com.macower.spring.proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * CGLibProxy动态代理类的实例 * * @author Macower * */ public class CGLibProxy implements MethodInterceptor { private Object targetObject;// CGLib需要代理的目标对象 public Object createProxyObject(Object obj) { this.targetObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); enhancer.setCallback(this); Object proxyObj = enhancer.create(); return proxyObj;// 返回代理对象 } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; if ("addUser".equals(method.getName())) {// 过滤方法 checkPopedom();// 检查权限 } obj = method.invoke(targetObject, args); return obj; } private void checkPopedom() { System.out.println(".:检查权限 checkPopedom()!"); } }

 

下面来测试下

[java] view plain copy print ?
  1. package com.macower.spring.proxy;  
  2.   
  3. public class Client {  
  4.   
  5.     public static void main(String[] args) {  
  6.   
  7.         UserManager userManager = (UserManager) new CGLibProxy()  
  8.                 .createProxyObject(new UserManagerImpl());  
  9.         System.out.println("-----------CGLibProxy-------------");  
  10.         userManager.addUser("Macower""root");  
  11.         System.out.println("-----------JDKProxy-------------");  
  12.         JDKProxy jdkPrpxy = new JDKProxy();  
  13.         UserManager userManagerJDK = (UserManager) jdkPrpxy  
  14.                 .newProxy(new UserManagerImpl());  
  15.         userManagerJDK.addUser("Macower""root");  
  16.     }  
  17.   
  18. }  

package com.macower.spring.proxy; public class Client { public static void main(String[] args) { UserManager userManager = (UserManager) new CGLibProxy() .createProxyObject(new UserManagerImpl()); System.out.println("-----------CGLibProxy-------------"); userManager.addUser("Macower", "root"); System.out.println("-----------JDKProxy-------------"); JDKProxy jdkPrpxy = new JDKProxy(); UserManager userManagerJDK = (UserManager) jdkPrpxy .newProxy(new UserManagerImpl()); userManagerJDK.addUser("Macower", "root"); } }

 

执行结果是:

[java] view plain copy print ?
  1. -----------CGLibProxy-------------  
  2. .:检查权限  checkPopedom()!  
  3. .: 掉用了UserManagerImpl.addUser()方法!   
  4. -----------JDKProxy-------------  
  5. .:检查权限  checkPopedom()!  
  6. .: 掉用了UserManagerImpl.addUser()方法!   

-----------CGLibProxy------------- .:检查权限 checkPopedom()! .: 掉用了UserManagerImpl.addUser()方法! -----------JDKProxy------------- .:检查权限 checkPopedom()! .: 掉用了UserManagerImpl.addUser()方法!

 

 

JDK代理是不需要以来第三方的库,只要要JDK环境就可以进行代理,它有几个要求

 

* 实现InvocationHandler
* 使用Proxy.newProxyInstance产生代理对象

* 被代理的对象必须要实现接口

 

CGLib 必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承

 

但是针对接口编程的环境下推荐使用JDK的代理

在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行

 

所以在是实际的开发当中,开发人员应该根据实际的需求来选择合适的代理工具。

 

总结完毕!

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Spring学习笔记(17)-----------Spring AOP总结(2))