一.jdk动态代理
(1)目标类
(2)织入类
(3)代理类
(4)接口
示例:
接口IUser
public interface IUser {
public void update();
public void save();
public void delete() throws SQLException ;
}
接口实现类(目标类)
public class UserImp implements IUser{
@Override
public void update() {
System.out.println("更新...");
}
@Override
public void save() {
System.out.println("保存..");
}
@Override
public void delete() {
System.out.println("删除.....");
}
}
织入类(增强类)
package com.test.jdk;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.InvocationHandler;
public class UserHandler implements InvocationHandler{
private Object target;
public UserHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] params)
throws Throwable {
System.out.println("操作之前提示....");
Object result = method.invoke(target, params);
return result;
}
}
测试类:
public class Test3 {
public static void main(String[] args) throws SQLException {
//目标类
IUser user = new UserImp();
//织入类
UserHandler handler = new UserHandler(user);
//代理类
IUser proxy = (IUser)Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), handler);
proxy.save();
proxy.update();
proxy.delete();
}
}
二.cglib动态代理
jdk动态代理有一个限制,它只能为接口创建代理示例,而CGLIB采用非常底层的字节码技术,可以为一个类创建子类,并且在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑。
(1)目标类
(2)织入类
(3)代理类
示例:
Userimp(不需要接口)
public class UserImp implements IUser{
@Override
public void update() {
System.out.println("更新...");
}
@Override
public void save() {
System.out.println("保存..");
}
@Override
public void delete() throws SQLException {
System.out.println("删除.....");
throw new SQLException("数据库异常");
}
}
织入类
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class UserCglibHandler implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clz){
enhancer.setSuperclass(clz); //设置需要创建子类的类
enhancer.setCallback(this); //通过字节码技术动态创建子类
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] params,
MethodProxy proxy) throws Throwable {
System.out.println("cglib操作之前.....");
Object result = proxy.invokeSuper(obj, params);
return result;
}
}
测试类:
public class Test4 {
public static void main(String[] args) throws SQLException {
UserImp user = new UserImp();
UserCglibHandler cglibHandler = new UserCglibHandler();
UserImp proxy = (UserImp)cglibHandler.getProxy(user.getClass());
proxy.delete();
proxy.update();
proxy.save();
}
}
三.Aop联盟
Spring Aop的底层是通过使用jdk动态代理或CGLIB动态代理技术为目标Bean织入横切逻辑,增强类有5种
(1)前置增强:org.springframework.aop.BeforeAdvice代表前置增强
(2)后置增强:prg.springframework.aop.AfterReturningAdvice代表后置增强
(3)环绕增强:org.aopalliance.intercept.MethodInterceptor代表环绕增强
(4)异常抛出增强:org.springframework.aop.ThrowsAdvice代表抛出异常增强
(5)引介增强:org.springframework.aop.IntroductionInterceptor,代表引介增强
前置增强BeforeAdvice:
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] params, Object obj)
throws Throwable {
System.out.println("aop联盟前置通知");
}
}
后置增强AfterReturnAdvice
public class AfterReturnAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object returnObject, Method method, Object[] params,
Object obj) throws Throwable {
System.out.println("aop联盟后置通知");
}
}
环绕增强:MethodInterceptorAdvice
public class MethodIntercptAdvice implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("环绕通知前...");
Object result = invocation.proceed();
System.out.println("环绕通知后...");
return result;
}
}
异常增强:ThrowAdvice
import org.springframework.aop.ThrowsAdvice;
public class ThrowAdvice implements ThrowsAdvice{
public void afterThrowing(Method method,Object[] params,Object target,Exception ex) throws Throwable{
System.out.println("抛出异常:"+ex.getMessage());
}
}
引介增强:IntroductionAdvice
接口:IMonitor
public interface IMonitor {
void setMonitor(boolean flag);
}
增强类
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
public class IntrodutionAdvice extends DelegatingIntroductionInterceptor implements IMonitor {
ThreadLocal<Boolean> status = new ThreadLocal<Boolean>();
@Override
public void setMonitor(boolean flag) {
status.set(flag);
}
public Object invoke(MethodInvocation invocation) throws Throwable{
Object obj = null;
if(status.get()!=null && status.get()){
System.out.println("引介增强通知.....");
obj = super.invoke(invocation);
}else{
obj = super.invoke(invocation);
}
return obj;
}
}
xml文件配置
<!-- 目标类 -->
<bean id="target" class="com.test.jdk.UserImp"></bean>
<!-- 织入前置通知类 -->
<bean id="beforeadvice" class="com.test.jdk.BeforeAdvice"></bean>
<!-- 织入后置通知类 -->
<bean id="afteradvice" class="com.test.jdk.AfterReturnAdvice"></bean>
<!-- 织入环绕通知类 -->
<bean id="methodintercptoradvice" class="com.test.jdk.MethodIntercptAdvice"></bean>
<!-- 织入异常通知类 -->
<bean id="throwsadvice" class="com.test.jdk.ThrowAdvice"></bean>
<!-- 织入异常通知类 -->
<bean id="introductionadvice" class="com.test.jdk.IntrodutionAdvice"></bean>
<!-- 代理类 -->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="target"
p:interceptorNames="introductionadvice"
p:interfaces="com.test.jdk.IMonitor"
p:proxyTargetClass="true"
/>
其中引介增强是一种比较特殊的增强类型,不是在目标方法周围织入增强,而是为目标类创建新的属性和方法,所以引介增强的连接点是类级别的,而非方法级别的。通过增强,可以为目标类添加一个接口的实现,即原来目标类未实现某个接口,通过增强可以为目标类创建实现某接口的代理。