annotation-config/>
Spring的AOP开发
AOP的概述
AOP的概念
AOP:
面向切面编程。
AOP出现是OOP的延伸,是OOP的扩展。
解决OOP中的一些问题。
AOP取代传统的纵向继承体系,采用横向抽取机制。
AOP的底层实现原理
代理机制(代理可以增强)
Spring实现AOP使用两种代理机制:
*JDK动态代理:
缺陷:
必须实现接口,否则不能产生代理对象
*Cglib动态代理:
第三方代理机制,采用字节码增强技术,其实是产生了类的子类对象
AOP的底层实现
JDK实现代理(了解)
publicclassMyJdkProxyimplementsInvocationHandler{
privateUserDaouserDao;
publicMyJdkProxy(UserDaouserDao){
this.userDao=userDao;
}
publicUserDaocreateProxy(){
UserDaoproxy=(UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(),this);
returnproxy;
}
@Override
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
if("save".equals(method.getName())){
System.out.println("权限校验===============");
returnmethod.invoke(userDao,args);
}
returnmethod.invoke(userDao,args);
}
}
Cglib实现代理(了解)
第三方的代理机制,对没有实现接口的类产生代理,使用的是字节码的增强技术,其实就是产生这个类的子类。
publicclassMyCglibProxyimplementsMethodInterceptor{
privateCustomerDaocustomerDao;
publicMyCglibProxy(CustomerDaocustomerDao){
this.customerDao=customerDao;
}
publicCustomerDaocreateProxy(){
//创建Cglib的核心类
Enhancerenhancer=newEnhancer();
//设置父类
enhancer.setSuperclass(CustomerDao.class);
//设置回调
enhancer.setCallback(this);
//生成代理
CustomerDaoproxy=(CustomerDao)enhancer.create();
returnproxy;
}
@Override
publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{
if("save".equals(method.getName())){
System.out.println("权限校验======================");
returnmethodProxy.invokeSuper(proxy,args);
}
returnmethodProxy.invokeSuper(proxy,args);
}
}
Spring的AOP的开发
AOP开发中的术语
Spring使用AspectJ的方式(XML方式)
AspectJ:
本身就是一个面向切面的框架,Spring把AspectJ引入进来作为自身AOP的开发。
【步骤一:
引入jar包】
引入aop联盟的包
spring的aop开发包
aspectj的开发包
spring整合aspectJ的包
【步骤二:
编写类】
【步骤三:
引入Spring的配置文件】
引入了aop的约束
xmlversion="1.0"encoding="UTF-8"?
>
//www.springframework.org/schema/beans"
xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xmlns:
aop="http:
//www.springframework.org/schema/aop"xsi:
schemaLocation="
http:
//www.springframework.org/schema/beanshttp:
//www.springframework.org/schema/beans/spring-beans.xsd
http:
//www.springframework.org/schema/aophttp:
//www.springframework.org/schema/aop/spring-aop.xsd">
【步骤四:
将类交给Spring】
--目标类:
-->
【步骤五:
AspectJ中的通知类型】
前置通知:
在目标方法执行之前执行。
后置通知:
在目标方法执行之后执行。
环绕通知:
在目标方法执行之前和之后执行。
阻止目标方法的执行。
异常抛出通知:
在目标方法执行出现异常的时候执行。
最终通知:
无路目标方法是否出现异常,最终通知总是会被执行。
引介通知
【步骤六:
切入点表达式的编写】
AspectJ中提供了切入点的表达式,用来指定哪些包下的哪些类需要被增强。
表达式基于execution函数完成的,execution(“切入点表达式”)。
表达式语法:
[方法的访问修饰符]方法的返回值包名.类名.方法名(参数)
1publicvoidcom.itheima.spring.dao.*Dao.save(..)
2voidcom.itheima.spring.dao.UserDao.save(..)
3*com.itheima.spring.dao.*.*(..)
4*com.itheima.spring.dao.UserDao+.*(..)
5*com.itheima.spring.dao..*Dao.*(..)
【步骤七:
编写切面类】
publicclassMyAspectXml{
publicvoidprivilegeCheck(){
System.out.println("权限校验===========");
}
}
交给Spring管理:
【步骤八:
配置前置增强】
--配置前置通知-->
config>
--切入点:
真正增强的方法-->
pointcutexpression="execution(*com.itheima.spring.demo3.LinkManDao.save(..))"id="pointcut1"/>
pointcutexpression="execution(*com.itheima.spring.demo3.LinkManDao.update(..))"id="pointcut2"/>
--配置AOP的切面-->
aspectref="myAspect">
--配置前置通知-->
beforemethod="privilegeCheck"pointcut-ref="pointcut1"/>
aspect>
config>
【步骤九:
编写测试类】
publicclassSpringDemo3{
@Test
publicvoiddemo1(){
ApplicationContextapplicationContext=newClassPathXmlApplicationContext("applicationContext.xml");
LinkManDaolinkManDao=(LinkManDao)applicationContext.getBean("linkManDao");
linkManDao.save();
linkManDao.update();
linkManDao.delete();
linkManDao.find();
}
}
Spring和Junit整合
【引入jar包】
spring-test-4.2.4.RELEASE.jar
【编写测试代码】
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:
applicationContext.xml")
publicclassSpringDemo3{
@Resource(name="linkManDao")
privateLinkManDaolinkManDao;
/*@Test
publicvoiddemo1(){
ApplicationContextapplicationContext=newClassPathXmlApplicationContext("applicationContext.xml");
LinkManDaolinkManDao=(LinkManDao)applicationContext.getBean("linkManDao");
linkManDao.save();
linkManDao.update();
linkManDao.delete();
linkManDao.find();
}*/
@Test
publicvoiddemo2(){
linkManDao.save();
linkManDao.update();
linkManDao.delete();
linkManDao.find();
}
}
Spring的AOP中的通知的详解
【前置通知】
指的是在目标方法执行之前执行一段增强。
前置通知可以获得切入点表达式。
【后置通知】
指的是在目标方法执行之后执行一段增强。
后置通知获得方法的返回值。
【环绕通知】
指的是在目标方法执行之前和之后进行增强。
阻止目标方法执行。
【异常抛出通知】
指的是在目标方法执行出现异常的时候执行的。
获得到异常的信息。
【最终通知】
指的是无论是否有异常,总是被执行的。