1.cglib动态代理例子
要导入cglib的jar包
package com.arvon.cglibproxydemo;
/**
* 目标类
*@author Huangwen
*2017-3-30
*/
public class Target {
public void mainLogicMethod(){
System.out.println("Target.mainLogicMethod()");
}
}
//----------------------------------------------------------------
package com.arvon.cglibproxydemo;
import java.lang.reflect.Method;
import java.util.List;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 目标类的拦截器
*@author Huangwen
*2017-3-30
*/
public class TargetInterceptor implements MethodInterceptor{
private Target target;
private List<Interceptor> interceptors;
public TargetInterceptor(Target target, List<Interceptor> interceptors) {
this.target = target;
this.interceptors = interceptors;
}
/**
* 产生代理对象
* @return
*/
public Object createProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(this.target.getClass());//设置产生的代理对象的父类
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method menthod, Object[] arg2,
MethodProxy arg3) throws Throwable {
//所有的拦截器执行拦截方法
for (Interceptor interceptor : interceptors) {
interceptor.interceptor();
}
menthod.invoke(target, arg2);
return null;
}
}
package com.arvon.cglibproxydemo;
/**
* 拦截器接口
*@author Huangwen
*2017-3-30
*/
public interface Interceptor {
/**
* 拦截方法
*/
public void interceptor();
}
/**
* 模拟安全性框架
*@author Huangwen
*2017-3-30
*/
public class Security implements Interceptor {
@Override
public void interceptor() {
System.out.println(">>>>>do something about security");
}
}
/**
* 模拟日志类框架
*@author Huangwen
*2017-3-30
*/
public class Logger implements Interceptor {
@Override
public void interceptor() {
System.out.println(">>>>>do something about logging");
}
}
package com.arvon.cglibproxydemo;
import java.util.ArrayList;
import java.util.List;
/**
* 测试类
*@author Huangwen
*2017-3-30
*/
public class Client {
public static void main(String[] args) {
Target target= new Target();
Logger logger = new Logger();
Security security = new Security();
List<Interceptor> interceptors = new ArrayList<Interceptor>();
interceptors.add(security);
interceptors.add(logger);
TargetInterceptor targetInterceptor = new TargetInterceptor(target, interceptors);
Target Proxy = (Target)targetInterceptor.createProxy();
Proxy.mainLogicMethod();
}
}
输出
>>>>>do something about security
>>>>>do something about logging
Target.mainLogicMethod()
--------------------------------------------------
浅剖Spring Aop机制
jdk的动态代理:
1、因为是用jdk的API做到的
2、代理对象是动态产生的
cglib产生的代理类是目标类的子类
注意事项:
1、拦截器中invoke方法体的内容就是代理对象方法体的内容
2、当客户端执行代理对象.方法时,进入到了拦截器的invoke方法体
aop的一些概念:
1、切面
事务、日志、安全性框架、权限等都是切面
2、通知
切面中的方法就是通知
3、目标类
4、切入点
只有符合切入点,才能让通知和目标方法结合在一起
5、织入:
形成代理对象的方法的过程
好处:
事务、日志、安全性框架、权限、目标方法之间完全是松耦合的
切入点表达式
execution(public * *(..)) 所有的公共方法
execution(* set*(..)) 以set开头的任意方法
execution(* com.xyz.service.AccountService.*(..)) com.xyz.service.AccountService类中的所有的方法
execution(* com.xyz.service.*.*(..)) com.xyz.service包中的所有的类的所有的方法
execution(* com.xyz.service..*.*(..)) com.xyz.service包及子包中所有的类的所有的方法
execution(* cn.itcast.spring.sh..*.*(String,?,Integer)) cn.itcast.spring.sh包及子包中所有的类的有三个参数
第一个参数为String,第二个参数为任意类型,
第三个参数为Integer类型的方法
springAOP的具体加载步骤:
1、当spring容器启动的时候,加载了spring的配置文件
2、为配置文件中所有的bean创建对象
3、spring容器会解析aop:config的配置
1、解析切入点表达式,用切入点表达式和纳入spring容器中的bean做匹配
如果匹配成功,则会为该bean创建代理对象,代理对象的方法=目标方法+通知
如果匹配不成功,不会创建代理对象
4、在客户端利用context.getBean获取对象时,如果该对象有代理对象则返回代理对象,如果代理对象,则返回目标对象
说明:如果目标类没有实现接口,则spring容器会采用cglib的方式产生代理对象,如果实现了接口,会采用jdk的方式
通知:
1、前置通知
1、在目标方法执行之前执行
2、无论目标方法是否抛出异常,都执行,因为在执行前置通知的时候,目标方法还没有执行,还没有遇到异常
2、后置通知
1、在目标方法执行之后执行
2、当目标方法遇到异常,后置通知将不再执行
3、后置通知可以接受目标方法的返回值,但是必须注意:
后置通知的参数的名称和配置文件中returning="var"的值是一致的
3、最终通知:
1、在目标方法执行之后执行
2、无论目标方法是否抛出异常,都执行,因为相当于finally
4、异常通知
1、接受目标方法抛出的异常信息
2、步骤
在异常通知方法中有一个参数Throwable ex
在配置文件中
<aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
5、环绕通知
1、如果不在环绕通知中调用ProceedingJoinPoint的proceed,目标方法不会执行
2、环绕通知可以控制目标方法的执行