宁波企业自助建站,seo实战,做局域网网站教程,柯桥区建设局网站AOP
AOP#xff0c;面向切面编程#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象#xff0c;一个对象包括静态的属性信息#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的抽象#xff0c;属性与属性、方法与方法、对象与对象都可以组成一个…AOP
AOP面向切面编程是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象一个对象包括静态的属性信息包括动态的方法信息等。而AOP是横向的对不同事物的抽象属性与属性、方法与方法、对象与对象都可以组成一个切面而用这种思维去设计编程的方式叫做面向切面编程
AOP思想的实现方案动态代理技术在运行期间对目标对象的方法进行增强代理对象同名方法内可以执行原有逻辑的同时嵌入执行其他增强逻辑或其他对象的方法 下面是AOP的实现思想 创建增强类编写前方法与后方法
public class MyAdvice {public void beforeAdvice(){System.out.println(执行增强前方法);}public void afterAdvice(){System.out.println(执行增前后方法);}
}
编写被增强类并编写一个方法用于增强
public class UserServiceImpl implements UserService {Overridepublic void show() {System.out.println(show...);}}
Bean后处理器去实现将Bean对象替换成代理类
public class MyBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {private ApplicationContext context;Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {//对指定方法进行增强if (bean instanceof UserService) {//获取增强方法MyAdvice myAdvice context.getBean(MyAdvice.class);Object proxyInstance Proxy.newProxyInstance(bean.getClass().getClassLoader(),bean.getClass().getInterfaces(),new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {myAdvice.beforeAdvice();method.invoke(bean, args);myAdvice.afterAdvice();return proxy;}});return proxyInstance;}return bean;}Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.context applicationContext;}
} XML文件配置如下 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsdbean iduserService classcom.zmt.service.impl.UserServiceImpl/beanbean classcom.zmt.processor.MyBeanPostProcessor/bean classcom.zmt.advice.MyAdvice/
/beans 执行测试代码 public class ApplicationTest {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(application.xml);UserService userService context.getBean(UserService.class);userService.show();}
} 执行结果如下 这种实现方式存在两个问题一个是需要被增强的Bean对象需要硬编码指定其次是增强方法也是被写死的如果需要修改被增强的类或是修改增强方法都需要修改代码。
那么我们在了解Spring中AOP时需要先了解如下几个概念 目标对象 Taeget 被增强的方法所在的对象 代理对象 Proxy 对目标方法进行增强后的对象客户端实际调用的对象 连接点 Joinpoint 目标对象中可以被增强的方法 切入点 Pointcut 目标对象中实际被增强的方法 通知\增强 Advice 增强部分的代码逻辑 切面 Aspect 增强和切入点的组合 织入 Weaving 将通知和切入点动态组合的过程 那么接下来给出基于XML的实现AOP的示例代码 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:aophttp://www.springframework.org/schema/aopxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdbean iduserService classcom.zmt.service.impl.UserServiceImpl/!--将增强类交给Spring管理--bean idmyAdvice classcom.zmt.advice.MyAdvice/aop:config!--配置切面表达式指定需要被增强的方法--aop:pointcut idmyPointcut expressionexecution(void com.zmt.service.impl.UserServiceImpl.show())/!--指定切点与哪些增强类结合--aop:aspect refmyAdviceaop:before methodbeforeAdvice pointcut-refmyPointcut//aop:aspect/aop:config
/beans
public class UserServiceImpl implements UserService {Overridepublic void show() {System.out.println(show...);}}
public class MyAdvice {public void beforeAdvice(){System.out.println(执行增强前方法);}public void afterAdvice(){System.out.println(执行增前后方法);}
} 测试代码如下 public class ApplicationTest {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(application.xml);UserService userService context.getBean(UserService.class);userService.show();}
} 运行结果如下 execution语法 execution([访问修饰符] 返回值类型 报名.类名.方法名(参数)) 访问修饰符可以省略不写返回值类型、某一级包名、类名、方法名可以使用 * 表示任意包名与类名之间使用单点 . 表示该包下的类使用双点 .. 表示该包以及子包下的类参数列表可以使用双点 .. 表示任意参数 XML文件下通知的配置类型 通知名称 配置方式 执行时机 前置通知 aop:before 目标方法执行之前执行 后置通知 aop:after-returning 目标方法执行之后执行目标方法异常时不再执行 环绕通知 aop:around 目标方法执行前后执行目标方法异常时环绕后方法不再执行 异常通知 aop:after-throwing 目标方法抛出异常时执行 最终通知 aop:after 不管目标方法是否有异常最终都会执行 环绕通知需要将连接点传入具体的增强类实现代码如下 public class MyAdvice {public void beforeAdvice(){System.out.println(执行增强前方法);}public void afterAdvice(){System.out.println(执行增前后方法);}public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println(环绕前通知。。。);Object proceed joinPoint.proceed();System.out.println(环绕后通知。。。);return proceed;}
} 增强方法在被调用时Spring可以为其传递一些必要参数 参数类型 作用 JoinPoint 连接点对象任何通知都可以使用可以获取当前目标对象目标方法参数等信息 ProceedingJoinPoint JoinPoint子类对象主要是在环绕通知中执行proceed()进而执行目标方法 Throwable 异常对象使用在异常通知中需要在配置文件中指出异常对象名称
除了上面实现AOP之外基于XML文件配置的实现方式还存在另一种实现方式通过实现接口来表示该增强类的具体操作。 public class MyAdvice2 implements MethodInterceptor {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(环绕前通知。。。。);Object res invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments());System.out.println(环绕后通知。。。。);return res;}
}
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:aophttp://www.springframework.org/schema/aopxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdbean iduserService classcom.zmt.service.impl.UserServiceImpl/bean idmyAdvice2 classcom.zmt.advice.MyAdvice2/aop:configaop:pointcut idmyPointcut expressionexecution(void com.zmt.service.impl.UserServiceImpl.show())/!-- 指定增强类与切点 --aop:advisor advice-refmyAdvice2 pointcut-refmyPointcut//aop:config
/beans 注意一个增强类可以实现多个Advice接口 AOP配置的两种语法形式不同点
语法形式不同
advisor是通过实现接口来确认通知的类型aspect是通过配置确认通知的类型更加灵活
可配置的切面数量不同
一个advisor只能配置一个固定通知和一个切点表达式一个aspect可以配置多个通知和多个切点表达式任意组合
使用场景不同
允许随意搭配情况下可以使用aspect进行配置如果通知类型单一、切面单一的情况下可以使用advisor进行配置在通知类型已经固定不用人为指定通知类型时可以使用advisor进行配置