Spring-Aop的两种代理方式
Spring-Aop两种代理方式:
1、JDK动态代理:用于目标类实现了接口;
2、Cglib动态代理:用于目标类没有实现接口;
spring会依据目标类是否实现接口来选择使用哪种代理方式(目标类:相当于需要被增强的类);
模拟场景:目标类:步兵类,需要上战场打仗(手提精心打造的木棍)
通知类(增强类):高级商店类,只要有士兵来就免费提供(精心打造的暴风大剑)
代理工厂类:需要一个士兵来使用商店的东西(这样才能把士兵与商店联系起来,士兵与商店本来是单独存在的相互不知道)
JDK动态代理实现:
创建maven项目引入spring-aop依赖,使用的是5.1版本
1、目标类需要实现接口,所以先创建一个接口:SoldierInterface(士兵类的接口)
package top.free;
/**
* 士兵接口
*/
public interface SoldierInterface {
public void begin();
}
2、创建目标类(步兵类去实现接口),也可以有其他的类(弓箭兵。。。)只要实现了士兵类,都是士兵。
package top.free;
/*
*步兵类
*/
public class Soldier implements SoldierInterface {
@Override
public void begin() {
System.out.println("弓箭士兵开始战斗");
}
}
3、通知(也叫增强):商店类
package top.free.advice;
public class Store {
public void Before(){
System.out.println("为士兵换上暴风大剑。。。");
}
public void After(){
System.out.println("士兵胜利归来。。。");
}
}
4、创建代理工厂:需要传递过来一个士兵(不管是步兵还是弓箭兵),返回一个被商店加强的士兵
package top.free.proxy;
import top.free.SoldierInterface;
import top.free.advice.Store;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyProxyFactory {
//传递的soldier就是需要被增强的士兵类,
public SoldierInterface MyProxyFactory(SoldierInterface soldier){
//通知,此时的商店类,在工厂中new出的实列
Store store = new Store();
SoldierInterface proxysoldier = (SoldierInterface) Proxy.newProxyInstance(
MyProxyFactory.class.getClassLoader(),//第一个参数:使用当前类的类加载器
soldier.getClass().getInterfaces(),//第二个参数:传递的soldier士兵对象的接口
new InvocationHandler() {//第三个参数,匿名内部类形式
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置调用商店的配置
store.Before();
//调用目标方法,soldier就是传递的士兵对象,args参数默认无参
Object invoke = method.invoke(soldier, args);
//后置,士兵执行完方法后调用
store.After();
return invoke;
}
}
);
return proxysoldier;
}
}
5、测试运行:
package top.free;
import top.free.proxy.MyProxyFactory;
public class App
{
public static void main(String[] args) {
//创建工厂
MyProxyFactory myProxyFactory = new MyProxyFactory();
//创建目标类(士兵对象),具体的实现是步兵类
SoldierInterface soldier = new Soldier();
//将创建的士兵传递给工厂,工厂中有商店帮忙打造士兵,用新士兵接收
SoldierInterface newSoldier = myProxyFactory.MyProxyFactory(soldier);
//开始
newSoldier.begin();
}
}
Cglib动态代理实现:
写Jdk代理时已引入spring相关依赖,此时maven项目中已有spring-core包,Spring5.1版本中,spring-core包中有关于Cglib的类,不需要引入cglib依赖
1、Cglib代理使用的是没有接口的目标类,所以直接创建弓箭兵:
package top.free;
/**
* Cglib目标类,没有接口,弓箭兵类
*/
public class BowsSoldier {
public void begin(){
System.out.println("开始射杀敌人。。。");
}
}
2、通知(商店类):
package top.free.advice;
public class Store {
public void Before(){
System.out.println("为士兵换上霸王弓。。。");
}
public void After(){
System.out.println("士兵胜利归来。。。");
}
}
3、创建代理工厂:需要一个弓箭兵,返回一个装备好的弓箭兵
package top.free.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import top.free.BowsSoldier;
import top.free.advice.Store;
import java.lang.reflect.Method;
public class MyCglibProxyFactory {
public BowsSoldier MyCglibProxyFactory(BowsSoldier solider){
//创建通知类
Store store = new Store();
//创建Enhance对象
Enhancer enhancer = new Enhancer();
//设置弓箭兵类对象
enhancer.setSuperclass(solider.getClass());
//设置回调方法
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//放在方法执行前,就是前置增强,装备弓箭
store.Before();
//执行方法,solider就是传递过来的弓箭兵对象
Object invoke = method.invoke(solider);
//后置增强
store.After();
return invoke;
}
});
//创建装备好的士兵
BowsSoldier target1= (BowsSoldier) enhancer.create();
return target1;
}
}
4、测试:
package top.free;
import top.free.proxy.MyCglibProxyFactory;
import top.free.proxy.MyProxyFactory;
public class App
{
public static void main(String[] args) {//创建代理工厂
MyCglibProxyFactory myCglibProxyFactory = new MyCglibProxyFactory();
//创建一个普通的弓箭兵
BowsSoldier soldier = new BowsSoldier();
//传递弓箭兵到工厂,工厂装备好后返回,接收一个装备精良的弓箭兵
BowsSoldier target = myCglibProxyFactory.MyCglibProxyFactory(soldier);
//装备精良的弓箭兵开始战斗
target.begin();
}
}