AOP编程概念
AOP编程也可以称为Spring动态代理开发 概念:通过代理,为原始类增加额外功能
好处:利于原始类的维护
为什么需要引入AOP(动态代理开发呢)
举个简单的例子
在没有引入AOP的时候
像我们业务层也就是Service层,一般适用于完成业务代码和DAO层调用的,但是存在一个问题
有时候我们需要引入日志,性能,我们会在业务层写很多冗余代码,这并不符合程序设计的理念
这其实跟我们生活中的一个例子相似:
上述房东就是找了代理帮他处理他不想干的杂活
由此:我们引入动态代理
AOP的底层就是通过动态代理实现的
AOP编程开发的步骤
- 原始对象(例如ServiceImpl)
- 额外功能 (日志,性能,事务)
- 切入点
- 组转切面
1.基于配置文件开发流程
写一个类实现MethodIntercepeter方法
通过实现invoke方法,调用原始类的方法,并且可以在它前后以及抛出异常时引入我们想要增加的功能
通过配置文件配置 aop切面
具体代码如下
public class Around implements MethodInterceptor {
/**
* invoke 方法的作用:额外功能书写在invoke,额外功能 可以写在原始方法之前前之后
* 确定:原始方法怎么运行
* @param methodInvocation 代表额外功能所增加给的那个原始方法 , methodInvocation.proceed(); 代表原始方法的运行
* @return 代表原始方法执行后的放回值,
* @throws Throwable
*/
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
//运行额外功能所增加给的按个原始方法
System.out.println("----------额外功能------");
Object ret= null;
ret = methodInvocation.proceed();
System.out.println("----------额外功能------");
return ret;
}
}
<bean id="around" class="com.huy.dynamic.Around"></bean>
<aop:config >
<!--所有方法加入功能-->
<aop:pointcut id="pc" expression="execution(* login(..)) or execution(* register(..))"/>
<!--组装:目的是把切入点与额外功能进行整合-->
<aop:advisor advice-ref="around" pointcut-ref="pc"></aop:advisor>
</aop:config>
这样就成功将我们需要增加的功能给引入了
2.通过注解方式
编写一个切面类,注入spring容器,同时配置文件中开启通过注解引入切面
/**
* 额外功能
* 切入点
*/
@Aspect
public class MyAspect {
@Pointcut("execution(* login(..)) || execution(* register(..))")
public void myPointcut(){}
@Around(value = "myPointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("------aspect- log------");
Object res = joinPoint.proceed();
return res;
}
}
<bean id="userService" class="com.huy.aspect.UserServiceImpl"></bean>
<!--切面:额外功能 切入点 组转切面-->
<bean id="around" class="com.huy.aspect.MyAspect"/>
<!--告诉spring基于注解进行AOP编程-->
<!-- proxy-target-class="true"就会让创建动态代理的方式就是Cglib-->
<aop:aspectj-autoproxy/>
底层动态代理的实现
一种是JDK的动态代理,一种是Cgilb动态代理方式
JDk的动态代理
其中类加载器的作用
public static void main(String[] args) {
//1.创建原始对象
UserService userService=new UserServiceImpl();
//2.JDK创建动态代理
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----log------");
Object ret = method.invoke(userService, args);
return ret;
}
});
userServiceProxy.login();
}
}
Cglib动态代理
CGlib创建动态代理原理:
通过父子继承关系创建代理对象,原始类作为父类,
代理类作为子类,这样既可以保证两者方法一致,调用原始方法,并且增加额外功能
public class TestCjlib {
public static void main(String[] args) {
UserService userService=new UserService();
//通过cjlib方法创建动态代理对象
//spring已经给我们引入了
Enhancer enhancer=new Enhancer();
enhancer.setClassLoader(userService.getClass().getClassLoader());
enhancer.setSuperclass(userService.getClass());
MethodInterceptor interceptor=new MethodInterceptor() {
//等同于InvocationHandler --invoke
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cjlib log-------");
Object ret = method.invoke(userService, objects);
return ret;
}
};
enhancer.setCallback(interceptor);
UserService userServiceProxy = (UserService) enhancer.create();
userServiceProxy.login("suns","1231241");
userServiceProxy.register("suns","12314");
}
}
JDK动态代理: Proxy.newProxyInstance()通过接口创建代理的实现类
CGlib动态代理:Enhancer enhancer=new Enhancer(),
enhancer.setClassLoader()
enhancer.setSuperclass()
enhancer.setCallback
enhancer.create()创建代理对象
通过继承父类来创建代理