面向切面的Spring<一>
来源:互联网 发布:order by sql 编辑:程序博客网 时间:2024/05/17 20:38
Spring提供了4种类型的AOP支持:
- 基于代理的经典Spring AOP;
- 纯POJO切面;
- @AspectJ注解驱动的切面;
- 注入式AspectJ切面(适用于Spring各个版本)
SpringAOP框架的一些必须要了解的关键知识
Spring通知是JAVA编写的
Spring所创建的通知都是用标准的Java类编写的。因此可以用普通Java开发一样的IDE来开发切面。而且,定义通知所应用的切点通常会使用注解或在Spring 配置文件里采用XML来编写。
Spring在运行时通知对象
通过在代理类中包裹切面,Spring在运行时期把切面织入到Spring管理的bean中。
直到应用需要被代理的bean时,Spring才创建代理对象。如果使用的是ApplicationContext的话,在ApplicationContext从BeanFactory中加载所有的bean的时候,Spring才会被创建到代理对象。因为Spring运行时才创建代理对象,所以我们不需要特殊的编译器来织入SpringAOP的切面。Spring只支持方法级别的连接点
因为Spring基于动态代理,所以Spring只支持方法级别连接点。这与一些其他的AOP框架是不同的,例如AspectJ和JBoss,除了方法切点,它们还提供了字段和构造器接入点。Spring缺少对字段连接点的支持,无法让我们创建细粒度的通知,例如拦截对象字段的修改。而且它不支持构造器连接点,我们就无法再bean创建时应用通知。
但是方法拦截可以满足绝大部分的需求。如果需要方法拦截之外的连接点拦截功能,我们可以利用AspectJ来补充SpringAOP的功能。
1. 注解方式实现AOP编程
步骤:
1) 先引入aop相关jar文件
2) bean.xml中引入aop名称空间
3) 开启aop注解
4) 使用注解
@Aspect 指定一个类为切面类
@Pointcut(“execution(* cn.itcast.e_aop_anno..(..))”) 指定切入点表达式
@Before(“pointCut_()”) 前置通知: 目标方法之前执行
@After(“pointCut_()”) 后置通知:目标方法之后执行(始终执行)
@AfterReturning(“pointCut_()”) 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing(“pointCut_()”) 异常通知: 出现异常时候执行
@Around(“pointCut_()”) 环绕通知: 环绕目标方法执行
下面是我项目中的maven配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cyy</groupId> <artifactId>Maven_01</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>Maven_01 Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.5.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency> <!-- https://mvnrepository.com/artifact/aspectj/aspectjrt --> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies></project>
//1. IUserDao.java// 接口public interface IUserDao { void save();}
//2. UserDao.java/** * 目标对象 * @author Jie.Yuan * */@Component // 加入容器public class UserDao implements IUserDao{ @Override public void save() { System.out.println("-----核心业务:保存!!!------"); }}
//3. Aop.java 切面类@Component@Aspect // 指定当前类为切面类public class Aop { // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象 @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") public void pointCut_(){ } // 前置通知 : 在执行目标方法之前执行@Before("pointCut_()") public void begin(){ System.out.println("开始事务/异常"); } // 后置/最终通知:在执行目标方法之后执行 【无论是否出现异常最终都会执行】 @After("pointCut_()") public void after(){ System.out.println("提交事务/关闭"); } // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】 @AfterReturning("pointCut_()") public void afterReturning() { System.out.println("afterReturning()"); } // 异常通知: 当目标方法执行异常时候执行此关注点代码 @AfterThrowing("pointCut_()") public void afterThrowing(){ System.out.println("afterThrowing()"); } // 环绕通知:环绕目标方式执行 @Around("pointCut_()") public void around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("环绕前...."); pjp.proceed(); // 执行目标方法 System.out.println("环绕后...."); }}
//4. bean.xml<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 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"> <!-- 开启注解扫描 --> <context:component-scan base-package="cn.itcast.e_aop_anno"></context:component-scan> <!-- 开启aop注解方式 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>
//App.javapublic class App { ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/e_aop_anno/bean.xml"); // 目标对象有实现接口,spring会自动选择“JDK代理” @Test public void testApp() { IUserDao userDao = (IUserDao) ac.getBean("userDao"); System.out.println(userDao.getClass()); userDao.save(); } // 目标对象没有实现接口, spring会用“cglib代理” @Test public void testCglib() { OrderDao orderDao = (OrderDao) ac.getBean("orderDao"); System.out.println(orderDao.getClass()); orderDao.save(); }}
2. XML方式实现AOP编程
Xml实现aop编程:
1) 引入jar文件 【aop 相关jar, 4个】
2) 引入aop名称空间
3)aop 配置
* 配置切面类 (重复执行代码形成的类)
* 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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 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"> <!-- dao 实例 --> <bean id="userDao" class="cn.itcast.f_aop_xml.UserDao"></bean> <bean id="orderDao" class="cn.itcast.f_aop_xml.OrderDao"></bean> <!-- 切面类 --> <bean id="aop" class="cn.itcast.f_aop_xml.Aop"></bean> <!-- Aop配置 --> <aop:config> <!-- 定义一个切入点表达式: 拦截哪些方法 --> <aop:pointcut expression="execution(* cn.itcast.f_aop_xml.*.*(..))" id="pt"/> <!-- 切面 --> <aop:aspect ref="aop"> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pt"/> <!-- 前置通知: 在目标方法调用前执行 --> <aop:before method="begin" pointcut-ref="pt"/> <!-- 后置通知: --> <aop:after method="after" pointcut-ref="pt"/> <!-- 返回后通知 --> <aop:after-returning method="afterReturning" pointcut-ref="pt"/> <!-- 异常通知 --> <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/> </aop:aspect> </aop:config></beans>
2. 切入点表达式
切入点表达式,
可以对指定的“方法”进行拦截; 从而给指定的方法所在的类生层代理对象。
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 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"> <!-- dao 实例 --> <bean id="userDao" class="cn.itcast.g_pointcut.UserDao"></bean> <bean id="orderDao" class="cn.itcast.g_pointcut.OrderDao"></bean> <!-- 切面类 --> <bean id="aop" class="cn.itcast.g_pointcut.Aop"></bean> <!-- Aop配置 --> <aop:config> <!-- 定义一个切入点表达式: 拦截哪些方法 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>--> <!-- 【拦截所有public方法】 --> <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>--> <!-- 【拦截所有save开头的方法 】 --> <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>--> <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 --> <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>--> <!-- 【拦截指定类的所有方法】 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>--> <!-- 【拦截指定包,以及其自包下所有类的所有方法】 --> <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>--> <!-- 【多个表达式】 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!-- 下面2个且关系的,没有意义 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!-- 【取非值】 --> <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/> <!-- 切面 --> <aop:aspect ref="aop"> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pt"/> </aop:aspect> </aop:config></beans>
3. Spring对jdbc支持
使用步骤:
1)引入jar文件
spring-jdbc-3.2.5.RELEASE.jar
spring-tx-3.2.5.RELEASE.jar
2) 优化
//UserDao.javapackage jdbc;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import javax.sql.DataSource;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;/** * Created by Administrator on 2017/2/3. */public class UserDao { //IOC容器注入 private DataSource dataSource; public void setDataSource(DataSource dataSource){ this.dataSource = dataSource; } public void save(){ String sql = "insert into t_dept(deptName) values('test')"; //使用jdbc模板工具类简化jdbc操作 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.update(sql); } public Dept findById(int id){ String sql = "select * from t_dept"; JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); //List<Map<String,Object>> list = jdbcTemplate.queryForList(sql); List<Dept> list = jdbcTemplate.query(sql, new RowMapper<Dept>() { //如何封装一行数据 @Override public Dept mapRow(ResultSet resultSet, int i) throws SQLException { Dept dept = new Dept(); dept.setDeptId(resultSet.getInt("deptId")); dept.setDeptName(resultSet.getString("deptName")); return dept; } }); System.out.println(list); return null; }}
//Dept.javapackage jdbc;/** * Created by Administrator on 2017/2/3. */public class Dept { private int deptId; private String deptName; public int getDeptId() { return deptId; } public void setDeptId(int deptId) { this.deptId = deptId; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } @Override public String toString() { return "Dept{" + "deptId=" + deptId + ", deptName='" + deptName + '\'' + '}'; }}
//bean.xml<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 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"> <!-- 1. 数据源对象: C3P0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property> <property name="user" value="root"></property> <property name="password" value="123456"></property> <property name="initialPoolSize" value="3"></property> <property name="maxPoolSize" value="10"></property> <property name="maxStatements" value="100"></property> <property name="acquireIncrement" value="2"></property> </bean> <!-- 2. 创建JdbcTemplate对象 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- dao 实例 --> <bean id="userDao" class="jdbc.UserDao"> <property name="dataSource" ref="dataSource"></property> </bean></beans>
//测试类public class App { //容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("jdbc/bean.xml"); @Test public void testApp(){ UserDao dao = (UserDao) ac.getBean("userDao"); //dao.save(); dao.findById(2); }}
别忘了在数据库中建相应的数据库、表,注意字段与实体类之间的对应。
- 面向切面的Spring<一>
- 面向切面的Spring
- 面向切面的spring
- 面向切面的Spring
- 面向切面的Spring
- 面向切面的Spring
- Spring面向切面编程一
- spring in action-面向切面的spring(一)
- Spring面向切面的编程
- Spring的面向切面AOP
- Spring AOP 面向切面编程(一)
- 面向切面的 Spring —— 什么是面向切面编程?
- Spring 第四章 面向切面的Spring
- Spring入门之面向切面的Spring
- 面向切面的 Spring —— 如何注入 AspectJ 切面?
- Spring 的AOP(面向切面编程)
- spring的AOP面向切面编程
- spring 面向切面编程AOP的原理
- Leetcode 111. Minimum Depth of Binary Tree
- 1059. Prime Factors (25)
- Linux系统启动流程简析
- 多线程知识小结(一)
- 《Linux启动过程分析》内核挂载根文件系统
- 面向切面的Spring<一>
- Swift3.0-视图控制器的生命周期
- dom4j解析
- python socket编程介绍
- [LeetCode]102. Binary Tree Level Order Traversal
- c++遍历搜索文件和文件夹
- 蓝桥杯 十字图打印
- 源码推荐:iOS开发商品展示的不同样式Demo和微信小程序开源项目库汇总
- 17年第一篇_SQL SHOW