合肥做网站,北京网站优化页面,在淘宝做网站可以改域名吗,网站建设店淘宝Spring学习 7 bean的生命周期8 AOP面向切面编程8.1 AOP相关术语8.2 AOP使用 7 bean的生命周期
bean的生命周期主要为bean实例化、bean属性赋值、bean初始化、销毁bean#xff0c;其中在实例化和初始化前后都使用后置处理器方法#xff0c;而InstantiationAwareBeanPostProce… Spring学习 7 bean的生命周期8 AOP面向切面编程8.1 AOP相关术语8.2 AOP使用 7 bean的生命周期
bean的生命周期主要为bean实例化、bean属性赋值、bean初始化、销毁bean其中在实例化和初始化前后都使用后置处理器方法而InstantiationAwareBeanPostProcessor 继承了BeanPostProcessor 可以看下这篇博客大致了解一下 一文读懂 Spring Bean 的生命周期 bean的作用域
单例Singleton在整个应用中只创建bean的一个实例原型Prototype每次注入或者通过Spring的应用上下文获取的时候都会创建一个新的bean实例会话Session在Web应用中为每个会话创建一个bean实例请求Rquest在Web应用中为每个请求创建一个bean实例
8 AOP面向切面编程
AOPAspect Oriented Programming面向切面编程利用 AOP 可以使得业务模块只需要关注核心业务的处理不用关心其他的如安全管理。可以不通过修改源代码的方式在主干功能里面添加新功能。
使用AOP相关的包百度网盘
8.1 AOP相关术语
通知Advice 通知定义了何时使用切面有以下五种类型的通知
前置通知Before在目标方法被调用之前调用通知功能后置通知After在目标方法完成之后调用通知此时不会关心方法的输出是什么返回通知After-returning在目标方法成功执行之后调用通知异常通知After-throwing在目标方法抛出异常后调用通知环绕通知Around通知包裹了被通知的方法在被通知的方法调用之前和调用之后执行自定义的行为
连接点Join point) 连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中并添加新的行为。 切点Pointcut 切点定义了何处使用切面。会匹配通知Advice所要织入的一个或多个连接点。我们通常使用 明确的类和方法名称或利用正则表达式定义所匹配的类和方法名称来指定这些切点。 切面Aspect 切面是通知和切点的结合。通知和切点共同定义了切面的全部内容——它是什么在何时和何处完成其功能。 引入Introduction 引入允许我们向现有的类添加新方法或属性。 目标对象Target Target是织入 Advice 的目标对象 织入Weaving 织入就是把通知Advice添加到目标对象具体的连接点上的过程 8.2 AOP使用
切入点表达式语法结构 execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )此外还可以对切入点进行限制因为“”在XML中有特殊含义所以在Spring的XML配置里面描述切点时我们可以使用and来代替“”。同样or和not可以分别用来代替“||”和“!” 基于注解 创建配置类ConfigAop package springstudy2;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;//创建ConfigAop配置类
Configuration //Configuration标记类作为配置类替换xml配置文件
EnableAspectJAutoProxy(proxyTargetClass true) //启用自动代理
ComponentScan(basePackages {springstudy2}) //开启注解扫描
public class ConfigAop {
}Configuration EnableAspectJAutoProxy(proxyTargetClass true) ComponentScan(basePackages {“springstudy2”}) 三个注解相当于以下代码 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/context xmlns:jdbchttp://www.springframework.org/schema/jdbc xmlns:jeehttp://www.springframework.org/schema/jee xmlns:txhttp://www.springframework.org/schema/txxmlns:utilhttp://www.springframework.org/schema/util xmlns:taskhttp://www.springframework.org/schema/task xsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd default-lazy-initfalse!-- 开启注解扫描 --context:component-scan base-packagespringstudy2/context:component-scan!-- 开启 Aspect 生成代理对象--aop:aspectj-autoproxy/aop:aspectj-autoproxy
/beans创建User类 package springstudy2;import org.springframework.stereotype.Component;//创建User对象
Component
public class User {public void add() {//int a 10 / 0;System.out.println(调用add方法...);}public void test() {System.out.println(调用test方法...);}
}创建代理 UserProxy 如果有多个代理可以通过Order注解指定优先级数字越小优先级越高 package springstudy2;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;//创建UserProxy对象
//增强的类
Component
Aspect //生成代理对象
Order(1)//代理优先级数字越小优先级越高
public class UserProxy {//相同切入点抽取Pointcut(value execution(* springstudy2.User.add(..)))public void pointdemo() { //pointdemo()方法的内容并不重要在这里它实际上应该是空的}//前置通知//Before 注解表示作为前置通知Before(value pointdemo())public void before() {System.out.println(在目标方法被调用之前调用通知功能.........);}Before(value execution(* springstudy2.User.test(..)))public void before1() {System.out.println(test 在目标方法被调用之前调用通知功能.........);}//后置通知After(value execution(* springstudy2.User.add(..)))public void after() {System.out.println(在目标方法完成之后调用通知.........);}//返回通知AfterReturning(value pointdemo())public void afterReturning() {System.out.println(在目标方法成功执行之后调用通知.........);}//异常通知AfterThrowing(value execution(* springstudy2.User.add(..)))public void afterThrowing() {System.out.println(在目标方法抛出异常后调用通知.........);}//环绕通知Around(value execution(* springstudy2.User.add(..)))public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(环绕之前在被通知的方法调用之前.........);//被增强的方法执行proceedingJoinPoint.proceed();System.out.println(环绕之后在被通知的方法调用之后.........);}
}上述代码中afterReturning 和 after 注解的执行顺序存在版本问题有争议据说从Spirng 5.2.7那一版开始通知注解的执行顺序如下不知道后面改没改。。。我的Spring5.3.9是这样
Around注解方法的前半部分业务逻辑Before注解方法的业务逻辑目标方法的业务逻辑AfterThrowing若目标方法有异常执行AfterThrowing注解方法的业务逻辑AfterReturning若目标方法无异常执行AfterReturning注解方法的业务逻辑After不管目标方法有无异常都会执行After注解方法的业务逻辑Around注解方法的后半部分业务逻辑Around注解方法内的业务逻辑若对ProceedingJoinPoint.proceed()方法没做捕获异常处理直接向上抛出异常则不会执行Around注解方法的后半部分业务逻辑若做了异常捕获处理则会执行 创建 PersonProxy 代理 package springstudy2;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;//创建PersonProxy对象
//增强的类
Component
Aspect //生成代理对象
Order(2)//代理优先级数字越小优先级越高
public class PersonProxy {Before(value execution(* springstudy2.User.add(..)))public void before() {System.out.println(person 在目标方法被调用之前调用通知功能.........);}
}测试类Test package springstudy2;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext context new AnnotationConfigApplicationContext(ConfigAop.class);//ConfigAop为配置类User user context.getBean(user, User.class);user.add();user.test();}
}执行结果 基于XML 在src目录下创建bean3.xml文件 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd!--创建对象--bean iduser classspringstudy2.User/beanbean iduserproxy classspringstudy2.UserProxy/beanbean idpersonproxy classspringstudy2.PersonProxy/beanaop:config!--切入点--aop:pointcut idp expressionexecution(* springstudy2.User.add(..))/!--配置切面--aop:aspect refuserproxy order1 !--通过 orde r确定优先级--!--增强作用在具体的方法上--!--methodbefore中 before 是UserProxy类中的方法名--aop:before methodbefore pointcut-refp/aop:before methodbefore pointcutexecution(* springstudy2.User.test(..))/aop:after methodafter pointcut-refp/aop:after-returning methodafterReturning pointcut-refp/aop:after-throwing methodafterThrowing pointcut-refp/aop:around methodaround pointcut-refp//aop:aspectaop:aspect refpersonproxy order2!--增强作用在具体的方法上--aop:before methodbefore pointcut-refp//aop:aspect/aop:config
/beans修改Test类 package springstudy2;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(bean3.xml);User user context.getBean(user, User.class);user.add();user.test();}
}基于XML的AOP执行结果 基于注解的AOP执行结果 注与注解执行顺序不一致原因是两者使用的AOP代理不同在基于注解的AOP中通知的执行顺序是确定的而多个切面执行顺序由Order注解来控制当没有指定Order注解时Spring会按照切面类的类名进行排序从字母顺序最小的切面开始执行依次递增在XML配置中around注解声明在before注解前面则around注解先执行否则before注解先执行
aop:after methodafter pointcut-refp/
aop:after-returning methodafterReturning pointcut-refp/
aop:after-throwing methodafterThrowing pointcut-refp/
aop:around methodaround pointcut-refp/
aop:before methodbefore pointcut-refp/
aop:before methodbefore pointcutexecution(* springstudy2.User.test(..))/