前言:最近在复习spring特记录于此,欢迎大家交流指正---QQ:767872620
本小例子使用cglib实现动态代理类:
cglib-nodep-2.2.2.jar下载地址:
http://download.csdn.net/detail/hollboy/5327795
代码如下:
目标类:(目标类(业务类)没有实现任何接口时使用cglib-nodep-2.2.2.jar实现AOP)
package cn.itcast.service.imp;
import cn.itcast.service.PersonService;
/**
*
* @author Mars
*1.拦截所有业务方法
*2。判断用户是否有权限,有权限就允许他执行业务方法,没有权限就不允许他执行业务方法
*是否有权限是根据user是否为null作为判断依据
*3.通过cglib-nodep-2.2.2.jar实现AOP
*/
public class PersonServiceBean2 {
public PersonServiceBean2(String user) {
super();
this.user = user;
}
public String getUser() {
return user;
}
public String user = null;
public PersonServiceBean2(){
}
public String getPersonName(Integer personid) {
return "xxx";
}
public void save(String name) {
System.out.println("我是save方法");
}
public void update(String name, Integer personid) {
System.out.println("我是update方法");
}
}
代理类:
package cn.itcast.aop;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import cn.itcast.service.imp.PersonServiceBean2;
/**
* 目标对象(业务类)没有实现任何业务接口,
* 但是得实现一个MethodInterceptor的接口
* @author Mars
*CGLIB可以生成目标类的子类,并重写父类的非final的方法
*/
public class CGlibProxyFactory implements MethodInterceptor {
Object targetObject=null;//代理目标对象
public Object createProxyIntance(Object targetObject){
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer(); //该类用于生成代理对象
//设置一个父类,也就是目标类
/**
* 继承目标类后会产生一个子类,会覆盖所有非final方法,再添加些自身的代码
*/
enhancer.setSuperclass(this.targetObject.getClass()); // 设置父类
//设置回调方法
enhancer.setCallback(this); //设置回调函数为本身
return enhancer.create();
}
/**
* 当代理对象调用时可以回调这个方法
* Object proxy:代理对象本身
* Method method:被拦截到的方法
* Object[] args:方法的输入参数
* MethodProxy methodProxy:方法的代理对象
* 环绕通知:
* 在一个方法执行之前和之后执行。
* 它使得通知有机会既在一个方法执行之前又在执行之后运行。
* 并且,它可以决定这个方法在什么时候执行,如何执行,甚至是否执行。
* 环绕通知经常在在某线程安全的环境下,你需要在一个方法执行之前和之后共享某种状态的时候使用。
* 请尽量使用最简单的满足你需求的通知。
* (比如如果前置通知(before advice)也可以适用的情况下不要使用环绕通知)。
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
PersonServiceBean2 bean = (PersonServiceBean2)this.targetObject;
Object result = null;//环绕通知
if(bean.getUser() !=null){
try {
//所谓通知就相关业务方法
//.......advice() -->前置通知
result = methodProxy.invoke(targetObject, args);
//.......afteradvice()--->后置通知
} catch (Exception e) {
// exceptionadvice()-->例外通知
}finally{
// finallyadvice()-->最终通知
}
}
return result;
}
}
测试类:
package junit.test;
import org.junit.BeforeClass;
import org.junit.Test;
import cn.itcast.aop.CGlibProxyFactory;
import cn.itcast.service.imp.PersonServiceBean2;
public class CGlibTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception{
}
@Test public void proxyTest(){
CGlibProxyFactory factory = new CGlibProxyFactory();
//有无权限的两种情况
// PersonServiceBean2 service = (PersonServiceBean2)factory.createProxyIntance(new PersonServiceBean2());
PersonServiceBean2 service = (PersonServiceBean2)factory.createProxyIntance(new PersonServiceBean2("xxxx"));
service.save("999999999");
}
}
总结:
AOP中概念:
Aspect(切面):指横切关注点的抽象即为切面,他与类类似,只是两者的关注点不一样,类是对物体特征的抽象,
而切面是横切关注点的抽象。(暂时理解为业务流程的,某环节的抽象)。
joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field(注解)或是构造器。
Pointcut(切入点):所谓切入点是指我们要对这些joinpoint进行拦截的定义。(暂时理解为拦截所有业务方法)
Advice(通知):所谓通知是指拦截到joinpoint之后索要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知、环绕通知
Target(目标对象):代理的目标对象
Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入。
Introduction(引入):在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或Field(注解 )
有关通知的相关可以参考: