本帖最后由 小石姐姐 于 2018-7-31 10:48 编辑
springAop(核心)
Spring Aop(核心)必须掌握:★概念:连接点 joinpoint 可能被增强的方法,一般在目标对象中定义
目标对象 target 要被增强的对象,增强该对象的方法
切点 pointcut 要被增强的方法
增强/通知 advice 具体对方法做哪些增强
切面 aspect 切点+通知/增强
代理对象 proxy 被增强后的对象,执行具体方法的时候是执行该对象的方法 AOP底层实现:JDK动态代理:[Java] 纯文本查看 复制代码 注意:被代理的对象必须要实现接口!!!!!
参考以前动态代理的编程
//创建一个使用jdk的proxy完成动态代理的工具
public class JDKProxyFactory implements InvocationHandler {
//创建代理和invoke方法都需要target,所以在创建时直接传入
private Object target;
public JDKProxyFactory(Object target) {
this.target = target;
}
// 创建代理对象
public Object createProxy() {
ClassLoader loader = target.getClass().getClassLoader();
Class[] interfaces = target.getClass().getInterfaces();
//返回代理对象
return Proxy.newProxyInstance(loader,interfaces, this);
}
//this:巧妙的利用了工具具有的target,为InvocationHandler对象设置target
// 在代理实例上处理方法调用并返回结果。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 功能增强操作
System.out.println("日志操作....");
return method.invoke(target, args);
}
}
public Test{
@Test
public void test01(){
//target:被增强的对象,省略创建,默认含有add方法
JDKProxyFactoryproxy= new JDKProxyFactory(target);
//代理对象的任何方法都会去执行*传入的this对象*的invoke方法
proxy.add();
}
} CGLIB动态代理:注意: jdk的动态代理只可以为实现接口的类去完成操作,而cglib它可以为没有实现接口的类去做代理,也可以为实现接口的类去做代理。 要单独使用CGLIB,那么需要导入cglib的jar包还需要一个asm相关jar包,但是spring框架的spring-core.jar包中已经集成了cglib与asm
[Java] 纯文本查看 复制代码 public class CglibProxyFactory implements MethodInterceptor {
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
// 创建代理对象
public Object createProxy() {
Enhancerenhance = new Enhancer();// 1.创建Enhancer
enhance.setSuperclass(target.getClass());// 2.传递目标对象的Class
enhance.setCallback(this);// 3.设置回调操作 (相当于InvocationHandler)
return enhance.create();
}
// 相当于InvocationHandler中的invoke
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxymethdoProxy) throws Throwable {
System.out.println("日志操作....");
return method.invoke(target, args); // 与jdk的proxy中操作类似
}
} Spring AOP编程:关注!!!:底层:哪一种动态代理
灌入关键字 Spring的传统aop编程(理解各对象关系):AOP中增强的方式:1. 前置通知 目标方法执行前增强 org.springframework.aop.MethodBeforeAdvice
2. 后置通知 目标方法执行后增强 org.springframework.aop.AfterReturningAdvice
3. 环绕通知 目标方法执行前后进行增强 org.aopalliance.intercept.MethodInterceptor
4. 异常抛出通知 目标方法抛出异常后的增强 org.springframework.aop.ThrowsAdvice
5. 引介通知 在目标类中添加一些新的方法或属性 org.springframework.aop.IntroductionInterceptor
通知需要实现其中的方式接口 导包: [Java] 纯文本查看 复制代码 导入相关jar包
spring-beans-4.2.4.RELEASE.jar
spring-context-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-expression-4.2.4.RELEASE.jar
//日志相关jar
commons-logging-1.2.jar
log4j-1.2.16.jar
spring-aop-4.2.4.RELEASE.jar
注意:导入aop联盟
com.springsource.org.aopalliance-1.0.0.jar
因为使用aspectJ需要导入相关jar包
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
基于aspectJ切点传统开发(掌握)应用场景:框架已经具有了成熟的通知,我们只需要给方法绑定 编写目标类:[Java] 纯文本查看 复制代码 //接口
public interface IOrderService {
void addOrder();
void updateOrder();
}
//实现类
public class OrderServiceImpl implements IOrderService {
@Override
public void addOrder() {
System.out.println("orderService add...");
}
@Override
public void updateOrder() {
System.out.println("orderService update...");
}
} 编写通知(Advice):[Java] 纯文本查看 复制代码 public classOrderHelper implements MethodBeforeAdvice, AfterReturningAdvice,MethodInterceptor {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知...");
}
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("后置通知...");
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("环绕前....");
Object value = mi.proceed();
System.out.println("环绕后....");
return value;
}
} 在配置文件中配置aop(五个对象):<?xml version="1.0"encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
-------------------配置aop命名空间-------------------------------
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
-----------------------------------------------------------------
------------------------配置要对谁增强----------------------------------------------
<!-- 目标target-->
<bean id="orderService" class="com.b3a4a.aop.OrderServiceImpl"></bean>
------------------------------------------------------------------------------------
------------------------配置增强方法的什么功能--------------------------------
<!-- 通知advice-->
<bean id="orderServiceAdvice"class="com.b3a4a.aop.OrderHelper"></bean>
------------------------------------------------------------------------------------
<!--以下不需要自己编写-->
<!-- 使用aop标签来完成切面与切点声明 -->
<!--完成自动代理,不需要提供名称-->
<aop:config>
<!-- 定义切点 配置要被增强的方法 -->
<aop:pointcut expression="execution(* com.b3a4a.aop.IOrderService.*(..))"
id="orderServicePointCut" />
<!-- 定义切面 将被增强的方法和要增强的功能绑定--->
<aop:advisor advice-ref="orderServiceAdvice"pointcut-ref="orderServicePointCut" />
</aop:config>
</beans>
<aop:config> 来声明要对aop进行配置
<aop:pointcut> 它是用于声明切点(简单说就是对哪些方法进行拦截)
<aop:advisor> 定义传统的aop的切面,传统的aop切面它只能包含一个切点与一个增强
execution /,eksɪ'kjuːʃ(ə)n/ 执行 单元测试@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= "classpath:applicationContext.xml")
public class AopTest {
//注入时不需要名称了,框架自动
@Autowired
private IOrderServiceorderService;
@Test
public void test1() {
orderService.updateOrder();
}
} Spring整合aspectj框架实现的aop(掌握):应用场景:自己定义的通知去绑定方法
AspectJ框架它定义的通知类型有6种1.前置通知Before 相当于BeforeAdvice
2.后置通知AfterReturning相当于AfterReturningAdvice
3.环绕通知Around 相当于MethodInterceptor
4.抛出通知AfterThrowing相当于ThrowAdvice
5.引介通知DeclareParents相当于IntroductionInterceptor
6.最终通知After不管是否异常,该通知都会执行
相比spring 的传统AOPAdvice多了一个最终通知 XML开发:编写目标类:相同 编写通知:[Java] 纯文本查看 复制代码 public classUserServiceHelper {
//由于不需要实现接口,因此需要在配置文件中配置方法
public void before() {
System.out.println("前置通知");
}
public void afterReturning(JoinPoint jp, Object val) {
System.out.println("后置通知");
}
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前....");
Object value = pjp.proceed(); // 执行目标行为
System.out.println("环绕后....");
return value;
}
public void afterThrowing(Throwable ex) {
System.out.println("发现了异常。。。。"+ex);
}
public void after(JoinPoint jp) {
System.out.println(jp.getSignature().getName());
System.out.println("最终通知");
}
} 配置文件中配置AOP:单元测试:相同 Annotation开发编写目标类相同,不过由于不进行XML配置,所以获得target对象需要@Service:注解创建对象 编写通知:@Component//用来创建通知对象
@Aspect//声明为切面
public class CustoemrServiceHelper {
//通知+切点
@Before(value="execution(* com.itnannan.aspectj_annotation.CustomerService.*(..))")
public void before(){
System.out.println("前置通知");
}
@After("execution(*com.itnannan.aspectj_annotation.CustomerService.*(..))")
public void after(){
System.out.println("后置通知");
}
@Around("execution(*com.itnannan.aspectj_annotation.CustomerServiceImpl.del(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕前通知");
Object object = pjp.proceed();
System.out.println("环绕后通知");
return object;
}
// 异常抛出通知
@AfterThrowing(value = "execution(* *.del(..))",throwing = "ex")
public void afterThrowing(JoinPoint jp, Throwable ex) {
System.out.println("异常抛出通知:" + ex);
}
} 单元测试:相同
|