我们编写满足特定业务逻辑的服务API。 涵盖所有服务API(如安全性,日志记录,审核,度量延迟等)的跨领域问题很少。 这是一个重复的非业务代码,可以在其他方法之间重用。 重用的一种方法是将这些重复的代码移入其自己的方法,并在服务API中调用它们,例如:

public class MyService{public ServiceModel service1(){isAuthorized();//execute business logic.}
}public class MyAnotherService{public ServiceModel service1(){isAuthorized()://execute business logic. }
}

上面的方法会起作用,但不会在不产生代码噪声的情况下将交叉关注点与业务逻辑混合在一起。 有另一种方法可以通过使用Aspect来解决上述要求,这种方法称为面向方面的编程(AOP)。 您可以使用AOP的不同方式-通过使用Spring AOP,JavaEE AOP。 在此示例中,我将尝试在Java EE应用程序中使用使用CDI的AOP。 为了解释这一点,我选择了一个非常简单的示例,该示例构建一个Web应用程序以从Database中获取少量记录并显示在浏览器中。

创建数据访问层

表结构为:

create table people(id INT NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL,place varchar(100),primary key(id));

让我们创建一个Model类来保存个人信息

package demo.model;
public class Person{private String id;private String name;private String place;public String getId(){ return id; } public String setId(String id) { this.id = id;}public String getName(){ return name; } public String setName(String name) { this.name = name;}public String getPlace(){ return place; } public String setPlace(String place) { this.place = place;}
}

让我们创建一个公开两种方法的数据访问对象–

  1. 获取所有人的细节
  2. 获取给定ID的一个人的详细信息
package demo.dao;import demo.common.DatabaseConnectionManager;
import demo.model.Person;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;public class PeopleDAO {public List<Person> getAllPeople() throws SQLException {String SQL = "SELECT * FROM people";Connection conn = DatabaseConnectionManager.getConnection();List<Person> people = new ArrayList<>();try (Statement statement = conn.createStatement();ResultSet rs = statement.executeQuery(SQL)) {while (rs.next()) {Person person = new Person();person.setId(rs.getString("id"));person.setName(rs.getString("name"));person.setPlace(rs.getString("place"));people.add(person);}}return people;}public Person getPerson(String id) throws SQLException {String SQL = "SELECT * FROM people WHERE id = ?";Connection conn = DatabaseConnectionManager.getConnection();try (PreparedStatement ps = conn.prepareStatement(SQL)) {ps.setString(1, id);try (ResultSet rs = ps.executeQuery()) {if (rs.next()) {Person person = new Person();person.setId(rs.getString("id"));person.setName(rs.getString("name"));person.setPlace(rs.getString("place"));return person;}}}return null;}
}

您可以使用自己的方法来获取新的连接。 在上面的代码中,我创建了一个静态实用程序,该实用程序返回了相同的连接。

创建拦截器

创建拦截器涉及2个步骤:

  1. 创建Interceptor绑定,该绑定创建带@InterceptorBinding注释的注释,该注释用于绑定拦截器代码和需要拦截的目标代码。
  2. 创建一个用@Interceptor注释的类,其中包含拦截器代码。 它包含用@AroundInvoke注释的方法,不同的生命周期注释, @AroundTimeout等。

让我们通过名称@LatencyLogger创建一个拦截器绑定

package demo;import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.*;
import static java.lang.annotation.ElementType.*;
import javax.interceptor.InterceptorBinding;@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface LatencyLogger {}

现在我们需要创建Interceptor代码,该代码以@Interceptor注释,并以上面创建的Interceptor绑定进行注释,即@LatencyLogger

package demo;
import java.io.Serializable;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;@Interceptor
@LatencyLogger
public class LatencyLoggerInterceptor implements Serializable{@AroundInvokepublic Object computeLatency(InvocationContext invocationCtx) throws Exception{long startTime = System.currentTimeMillis();//execute the intercepted method and store the return valueObject returnValue = invocationCtx.proceed();long endTime = System.currentTimeMillis();System.out.println("Latency of " + invocationCtx.getMethod().getName() +": " + (endTime-startTime)+"ms");return returnValue;}
}

上面的代码中有两个有趣的事情:

  1. 使用@AroundInvoke
  2. 传递给方法的InvocationContext类型的参数

@AroundInvoke将方法指定为拦截器方法。 一个Interceptor类只能有一个带有此注释的方法。 每当目标方法被拦截时,其上下文都会传递给拦截器。 使用InvocationContext可以获取方法的详细信息,并将参数传递给该方法。

我们需要在WEB-INF / beans.xml文件中声明上述拦截器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"bean-discovery-mode="all"><interceptors><class>demo.LatencyLoggerInterceptor</class></interceptors>
</beans>

创建带有拦截器注释的服务API

我们已经创建了Interceptor绑定和被执行的拦截器。 现在让我们创建服务API,然后使用Interceptor绑定对其进行注释

/** To change this license header, choose License Headers in Project Properties.* To change this template file, choose Tools | Templates* and open the template in the editor.*/
package demo.service;import demo.LatencyLogger;
import demo.dao.PeopleDAO;
import demo.model.Person;
import java.sql.SQLException;
import java.util.List;
import javax.inject.Inject;public class PeopleService {@InjectPeopleDAO peopleDAO;@LatencyLoggerpublic List<Person> getAllPeople() throws SQLException {return peopleDAO.getAllPeople();}@LatencyLoggerpublic Person getPerson(String id) throws SQLException {return peopleDAO.getPerson(id);}}

我们已经用Interceptor绑定@LatencyLogger注释了服务方法。 另一种方法是在类级别进行注释,然后将注释应用于类的所有方法。 还要注意的另一件事是@Inject批注,该批注注入实例,即将依赖项注入到类中。

接下来是连接Controller和View以显示数据。 控制器是servlet,视图是使用JSTL标记的纯JSP。

/** To change this license header, choose License Headers in Project Properties.* To change this template file, choose Tools | Templates* and open the template in the editor.*/
package demo;import demo.model.Person;
import demo.service.PeopleService;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@WebServlet(name = "AOPDemo", urlPatterns = {"/AOPDemo"})
public class AOPDemoServlet extends HttpServlet {@InjectPeopleService peopleService;@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try {List<Person> people = peopleService.getAllPeople();Person person = peopleService.getPerson("2");request.setAttribute("people", people);request.setAttribute("person", person);getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);} catch (SQLException ex) {Logger.getLogger(AOPDemoServlet.class.getName()).log(Level.SEVERE, null, ex);}}
}

上面的servlet可在http:// localhost:8080 /获得。

/ AOPDemo。 它获取数据并重定向到视图以显示该数据。 请注意,该服务也已使用@Inject注释注入。 如果没有注入依赖项,而是使用new创建依赖项,则拦截器将无法工作。 这是我在构建此样本时意识到的重要一点。

呈现数据的JSP将是

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>AOP Demo</title></head><body><h1>Hello World!</h1><table><tr><th>Id</th><th>Name</th><th>Place</th></tr><c:forEach items="${requestScope.people}" var="person"><tr><td><c:out value="${person.id}"/></td><td><c:out value="${person.name}"/></td><td><c:out value="${person.place}"/></td></tr></c:forEach></table><br/>Details for person with id=2<c:out value="Name ${person.name} from ${person.place}" /></body>
</html>

这样,您将可以使用Interceptor构建一个非常简单的应用程序。 感谢您的阅读,并一直与我在一起。 请分享您的查询/反馈作为评论。 并在您的朋友之间分享这篇文章!

翻译自: https://www.javacodegeeks.com/2014/09/simple-aspect-oriented-programming-aop-using-cdi-in-javaee.html

在JavaEE中使用CDI的简单面向方面的编程(AOP)相关推荐

  1. javaee编程题_在JavaEE中使用CDI的简单面向方面的编程(AOP)

    javaee编程题 我们编写满足特定业务逻辑的服务API. 涵盖所有服务API(如安全性,日志记录,审核,度量延迟等)的跨领域问题很少. 这是一个重复的非业务代码,可以在其他方法之间重用. 重用的一种 ...

  2. 1.面试中如何回答“请简单介绍一下Ioc、Aop”,建议熟读并背诵

    对Spring两大特性Ioc.Aop的简单理解 1.Ioc(控制反转)和DI(依赖注入):Spring是通过依赖注入的方式达到控制反转的.IOC是一种设计思想,DI是一种方法. 控制反转就是为了达到代 ...

  3. Spring--官方文档部分翻译(第五章 面向Aspect的编程-AOP)

    AOP通过提供程序设计的另一种思路扩展了OOP,OOP的核心元素是class,而AOP的核心是Aspect. Aspect使得关注点模块化. AOP是spring的核心模块.虽然LOC容器不依赖AOP ...

  4. java切面编程 切面概念,面向切面编程(AOP)初探

    面向对象编程通过设计和语言本身提供的模块化.封装.继承.多态来实现软件复用.尽管OOP在建模以及实现复杂软件方面非常成功,它仍然有一些问题.面向切面编程(AOP)被认为是一项有前途的新技术,它通过对交 ...

  5. 使用codeigniter_使用CodeIgniter探索面向方面的编程,第2部分

    使用codeigniter In the previous part of this series we learned what Aspect Oriented Programming (AOP) ...

  6. 使用Servlet 3.0,Redis / Jedis和CDI的简单CRUD –第2部分

    在本文中,我们将重点介绍CDI和Servlet 3.0. 您可以在此处看到第1部分. 让我们从CDI开始. 当我开始撰写源自该系列的文章时,我并没有考虑撰写CDI. 真诚地说,我以前从未使用过. 这篇 ...

  7. 使用Servlet 3.0,Redis / Jedis和CDI的简单CRUD –第1部分

    在这篇文章中,我们将构建一个简单的用户界面. 数据将存储在Redis中. 为了与Redis交互,我们将使用Jedis库. CDI用于Depedency Injection,而Servlet 3.0用于 ...

  8. unity中3dUI或者模型始终面向摄像机,跟随摄像机视角旋转丨视角跟随丨固定视角

    视角跟随 本脚本为一个目标跟随 unity中3dUI或者模型始终面向摄像机,跟随摄像机视角旋转 使用方法超级简单,对于一个资深的Ctrl+cv程序极为友好 不多讲解直接上代码 代码模块 public ...

  9. JAVAEE框架整合技术之Spring02-AOP面向切面编程技术

    Spring新注解 Spring5.0之后的注解称为新注解 使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置 注解 说明 @Configuration 表示当前类是一个配置类,用于 ...

最新文章

  1. 用拉链法实现哈希算法的运算
  2. 安波副教授:分布式人工智能进展与趋势
  3. 运维基础(13)日志切割工具 Logrotate
  4. python基础函数图_Python基础:函数
  5. 我最喜欢的IntelliJ IDEA功能
  6. Nginx根据路径设置静态资源
  7. java volatitl_Java中的关键字volatitle
  8. Java Exceptions
  9. 箫 音之乐 生(声)之乐
  10. 汉字的动态编码与显示方案
  11. Laravel5中基于jQuery实现分层级的类目树结构方法
  12. Dubbo-admin无法显示Group分组信息
  13. resize view from nib引起的子控制器视图(childviewcontroller)部分区域无响应
  14. 证明n次根号下n阶乘等价于n/e
  15. .net中的lock
  16. PowerDesigner下载安装破解
  17. 视频超分:Zooming Slow-Mo(Zooming Slow-Mo: Fast and Accurate One-Stage Space-Time Video Super-Resolution)
  18. STM32F030 IIC2通用读写24C02、24C16、24C32、24C64等例程
  19. 淘宝天猫API详情接口调用分享
  20. Android 翻页效果 电子书 (转)

热门文章

  1. 消费端整合SpringCloudGateway
  2. 用idea添加一个模块
  3. RecyclerView多布局的简单使用
  4. java aop 实例_Spring aop 简单示例
  5. 存储过程内基础语法---补充while循环
  6. 带Quarkus的Qute模板
  7. 不同的Hibernate命名策略
  8. java 反射 速度_Java反射,但速度更快
  9. java web源代码_检测Java Web应用程序而无需修改其源代码
  10. spring boot缓存_Spring Boot和缓存抽象