Spring AOP
AOP
1.将散布在系统中的公共功能,提取封装成独立的模块
2.采用代理机制组装起来运行,在不改变原程序的基础上对代码段进行增强处理,增加新的功能
先对Spring AOP里面几个名词进行说明。
- 切面(Aspect)
- 通知和切点的结合
- 切面使用通用类或者在普通类中加@AspectJ
- 连接点(Join point)
- 应用执行中插入切面的一个点
- 调用方法,抛出异常,修改字段
- 方法执行
- 通知(Advice)
- 切面的工作
- 切入点(Pointcut)
- 匹配通知要织入的一个(以上)连接点
- 类名,方法名指定
- 引入(Introduction)
- 向现有类添加方法或属性
- 目标对象(Target Object)
- 被一个(以上)切面通知的对象
- 代理类
- 织入(Weaving)
- 切面应用到目标对象,创建新的代理对象
- 编译期,类加载期,运行期织入
目的
1.A从系统中分离出切面,独立于业务逻辑实现,在程序执行时织入程序中运行
- 切面,可重用的公共模块,比如,日志,事务等
2.配置AOP主要使用aop命名空间下的元素完成。可以实现定义切入点和织入增强等操作
3.Spring提供的增强处理类型包括:前置增强、后置增强、环绕增强、异常抛出增强、最终增强等
作用
1.实现系统日志功能
a.业务介绍:将业务逻辑方法的调用信息输出到控制台
b.AOP思路:分别编写业务逻辑代码和“增强”代码,运行时再组装
c.步骤:
1)添加jar包
2)编写业务逻辑接口和实现类,编码时无需关心其他功能
d.定义切入点
1)public * addUser(com.xuetang9.demo.entity.User)
2)public void *(com.xuetang9.demo.entity.User)
3)public void addUser(..) 不知道参数类型
4)* com.xuetang9.demo.service.*.*(..) service包所有的方法
5)* com.xuetang9.demo.service..*.*(..) 等 service包及其子包所有的方法
2.增强类型
a.异常抛出增强:目标方法抛出异常时织入增强处理
ThrowsAdvice接口中并没有定义任何方法,但是我们在定义异常抛出的增强方法时必须遵守以下方法签名:
void afterThrowing ( [Method method, Object[] arguments, Object target) Throwable ex )
注意:方法名必须是afterThrowing。方法的入参只有最后一个是必须的,前三个入参是可选的,但是前三个参数要么都提供,要么一个也不提供。正确的声明方法举例:
1)afterThrowing(Method method, Object[] args, Object target, SQLException ex)
2)afterThrowing(SQLException ex)
3)afterThrowing(RuntimeException ex)
错误的声明方法举例:
1)catchThrowing(RuntimeException ex):方法名错误
2)afterThrowing(Method method, RuntimeException ex):参数列表错误
b.环绕增强:在目标方法的前后都可以织入增强处理
1)功能最强大的增强处理,Spring把目标方法的控制权全部在它手中
2)可以获取或修改目标方法的参数、返回值。可以对它进行异常处理,甚至可以决定目标方法是否执行
c.前置增强
d.后置增强
e.最终增强
范例:
1.实体类及其配置文件
a.实体类 -- User类
1 package com.Elastic.SpringDemo2.ivy.entity; 2 3 import java.io.Serializable; 4 5 public class User implements Serializable { 6 private String loginName; 7 private String loginPass; 8 9 public String getLoginName() { 10 return loginName; 11 } 12 public void setLoginName(String loginName) { 13 this.loginName = loginName; 14 } 15 public String getLoginPass() { 16 return loginPass; 17 } 18 public void setLoginPass(String loginPass) { 19 this.loginPass = loginPass; 20 } 21 22 }
b.实体类配置文件 -- User.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2016-7-5 22:38:24 by Hibernate Tools 3.4.0.CR1 --> 5 <hibernate-mapping> 6 <class name="com.Elastic.SpringDemo2.ivy.entity.User" table="user"> 7 <id name="loginName" type="java.lang.String"> 8 <column name="userName" /> 9 <generator class="assigned" /> 10 </id> 11 <property name="loginPass" type="java.lang.String"> 12 <column name="passWord" /> 13 </property> 14 </class> 15 </hibernate-mapping>
2.hibernate配置文件 -- hibernate.cfg.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 8 <property name="hibernate.connection.password">root</property> 9 <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernatedb</property> 10 <property name="hibernate.connection.username">root</property> 11 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 12 13 <property name="show_sql">true</property> 14 <property name="format_sql">true</property> 15 16 <mapping resource="com/Elastic/SpringDemo2/ivy/entity/User.hbm.xml"/> 17 </session-factory> 18 </hibernate-configuration>
3.util包
a.HibernateUtil类
1 package com.Elastic.SpringDemo2.ivy.util; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 public final class HibernateUtil { 7 private static Configuration cfg = null; 8 private static SessionFactory sessionFactory = null; 9 10 //本地线程 11 public static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>(); 12 13 static{ 14 cfg = new Configuration().configure(); 15 sessionFactory = cfg.buildSessionFactory(); 16 } 17 18 public static Session getSession(){ 19 Session session = threadLocal.get(); 20 if (null == session || !session.isOpen()) { 21 session = sessionFactory.openSession(); 22 threadLocal.set(session); 23 } 24 return session; 25 } 26 }
4.dao包
a.IBaseDao接口
1 package com.Elastic.SpringDemo2.ivy.dao; 2 3 import java.io.Serializable; 4 import java.util.List; 5 import java.util.Map; 6 7 import org.hibernate.Session; 8 import org.hibernate.criterion.DetachedCriteria; 9 public interface IBaseDao<T> { 10 /** 11 * 12 * <p> 13 * <h3>方法功能描述:获取Session对象</h3> 14 * </p> 15 * @return 16 * @procedure 执行过程 17 * @see IBaseDao 18 */ 19 Session getSession(); 20 21 /** 22 * 23 * <p> 24 * <h3>方法功能描述:保存数据</h3> 25 * </p> 26 * @param record 需要保存的对象 27 * @procedure 执行过程 28 * @see IBaseDao 29 */ 30 void save(T record); 31 32 /** 33 * 34 * <p> 35 * <h3>方法功能描述:根据主键删除对应的数据</h3> 36 * </p> 37 * @param id 38 * @procedure 执行过程 39 * @see IBaseDao 40 */ 41 //不明确id的类型,就用Serializable 42 void delete(Serializable id); 43 44 /** 45 * 46 * <p> 47 * <h3>方法功能描述:根据数据对象删除数据库中对应的数据</h3> 48 * </p> 49 * @param record 50 * @procedure 执行过程 51 * @see IBaseDao 52 */ 53 void delete(T record); 54 55 /** 56 * 57 * <p> 58 * <h3>方法功能描述:根据指定的对象修改对应的数据</h3> 59 * </p> 60 * @param record 61 * @procedure 执行过程 62 * @see IBaseDao 63 */ 64 void update(T record); 65 66 /** 67 * 68 * <p> 69 * <h3>方法功能描述:根据主键查询对应的数据</h3> 70 * </p> 71 * @param id 72 * @return 返回查找到的数据,如果没有返回null 73 * @procedure 执行过程 74 * @see IBaseDao 75 */ 76 T findById(Serializable id); 77 78 /** 79 * 80 * <p> 81 * <h3>方法功能描述:根据指定的hql语句和参数查询语句</h3> 82 * </p> 83 * @param hql 需要执行的查询的HQL语句 84 * @param params 执行的查询的HQL语句所需的参数,如果没有填写null 85 * @return 返回查询数据的集合,如果出现异常返回null 86 * @procedure 执行过程 87 * @see IBaseDao 88 */ 89 List<T> find(String hql,Map<String, Object> params); 90 91 /** 92 * 93 * <p> 94 * <h3>方法功能描述:根据指定的HQL语句和参数以及分页所需的数据执行查询</h3> 95 * </p> 96 * @param hql 需要执行的查询的HQL语句 97 * @param pageIndex 需要查询的页数 98 * @param pageSize 每页显示的数据条数 99 * @param params 执行的查询的HQL语句所需的参数,如果没有填写null 100 * @return 返回分页查询的结果,是一个Map对象,该对象包含<blockquote> 101 * <b>data</b>:查询结果的数据集合是一个List对象<br> 102 * <b>pageIndex</b>:当前查询的页数<br> 103 * <b>pageSize</b>:每页显示的数据条数<br> 104 * <b>total</b>:数据的总条数<br> 105 * <b>pageTotal</b>:数据的总页数<br> 106 * <b>hasPrev</b>:是否有上一条数据<br> 107 * <b>hasNext</b>:是否有下一条数据<br> 108 * </blockquote> 109 * @procedure 执行过程 110 * @see IBaseDao 111 */ 112 Map<String, Object> find(String hql, int pageIndex, int pageSize, Map<String, Object> params); 113 114 /** 115 * 116 * <p> 117 * <h3>方法功能描述:分页查询数据</h3> 118 * </p> 119 * @param pageIndex 需要查询的页数 120 * @param pageSize 每页显示的数据条数 121 * @return 返回分页查询的结果,是一个Map对象,该对象包含<blockquote> 122 * <b>data</b>:查询结果的数据集合是一个List对象<br> 123 * <b>pageIndex</b>:当前查询的页数<br> 124 * <b>pageSize</b>:每页显示的数据条数<br> 125 * <b>total</b>:数据的总条数<br> 126 * <b>pageTotal</b>:数据的总页数<br> 127 * <b>hasPrev</b>:是否有上一条数据<br> 128 * <b>hasNext</b>:是否有下一条数据<br> 129 * </blockquote> 130 * @procedure 执行过程 131 * @see IBaseDao 132 */ 133 Map<String, Object> find(int pageIndex, int pageSize); 134 135 /** 136 * 137 * <p> 138 * <h3>方法功能描述:根据DetachedCriteria 对象设置的条件查询数据,该功能不具备分页操作</h3> 139 * </p> 140 * @param detachedCriteria 需要设置的对象查询条件 141 * @return 返回查询数据的集合,如果出现异常返回null 142 * @procedure 执行过程 143 * @see IBaseDao 144 */ 145 List<T> find(DetachedCriteria detachedCriteria); 146 147 148 /** 149 * 150 * <p> 151 * <h3>方法功能描述:根据DetachedCriteria 对象设置的条件进行分页查询</h3> 152 * </p> 153 * @param detachedCriteria 需要设置的对象查询条件 154 * @param pageIndex 需要查询的页数 155 * @param pageSize 每页显示的数据条数 156 * @return 返回分页查询的结果,是一个Map对象,该对象包含<blockquote> 157 * <b>data</b>:查询结果的数据集合是一个List对象<br> 158 * <b>pageIndex</b>:当前查询的页数<br> 159 * <b>pageSize</b>:每页显示的数据条数<br> 160 * <b>total</b>:数据的总条数<br> 161 * <b>pageTotal</b>:数据的总页数<br> 162 * <b>hasPrev</b>:是否有上一条数据<br> 163 * <b>hasNext</b>:是否有下一条数据<br> 164 * </blockquote> 165 * @procedure 拼接HQL语句 166 * @see IBaseDao 167 */ 168 Map<String, Object> find(DetachedCriteria detachedCriteria, int pageIndex, int pageSize); 169 170 171 172 }
b.IBaseDao接口实现类 -- BaseDao
1 package com.Elastic.SpringDemo2.ivy.dao; 2 3 import java.io.Serializable; 4 import java.lang.reflect.ParameterizedType; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 import org.hibernate.Criteria; 10 import org.hibernate.Query; 11 import org.hibernate.Session; 12 import org.hibernate.criterion.DetachedCriteria; 13 import org.hibernate.criterion.Projections; 14 15 import com.Elastic.SpringDemo2.ivy.util.HibernateUtil; 16 //忽略警告 17 @SuppressWarnings({ "rawtypes", "unchecked" }) 18 public class BaseDao<T> implements IBaseDao<T>{ 19 20 private Class entityClass; 21 22 public BaseDao(){ 23 entityClass = this.getEntityClass(); 24 } 25 26 /** 27 * 28 * <p> 29 * <h3>方法功能描述:根据反射得到当前泛型参数(实体类)的数据类型</h3> 30 * </p> 31 * @return 32 * @procedure 执行过程 33 * @see BaseDao 34 */ 35 private Class getEntityClass(){ 36 try { 37 ParameterizedType paramsType = (ParameterizedType)this.getClass().getGenericSuperclass();//只能通过父类得到 38 return (Class)paramsType.getActualTypeArguments()[0]; 39 } catch (Exception e) { 40 e.printStackTrace(); 41 } 42 return null; 43 } 44 45 @Override 46 public Session getSession() { 47 return HibernateUtil.getSession(); 48 } 49 50 private Map<String, Object> createPageData(List<T> data, int pageIndex, int pageSize, int total) { 51 Map<String, Object> map = new HashMap<String, Object>(); 52 53 //获得总页数 54 int pageTotal = (int)Math.ceil((double)total / pageSize); 55 map.put("data", data); 56 map.put("pageIndex", pageIndex); 57 map.put("pageSize", pageSize); 58 map.put("total", total); 59 map.put("pageTotal", pageTotal); 60 61 //boolean,若没赋值,默认true 62 map.put("hasPrev", pageIndex > 1); 63 map.put("hasNext", pageIndex < pageTotal); 64 return map; 65 } 66 67 /* (non-Javadoc) 68 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#save(java.lang.Object) 69 */ 70 @Override 71 public void save(T record) { 72 this.getSession().save(record); 73 74 } 75 76 /* (non-Javadoc) 77 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#delete(java.io.Serializable) 78 */ 79 @Override 80 public void delete(Serializable id) { 81 this.getSession().delete(this.findById(id)); 82 83 } 84 85 /* (non-Javadoc) 86 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#delete(java.lang.Object) 87 */ 88 @Override 89 public void delete(T record) { 90 this.getSession().delete(record); 91 92 } 93 94 /* (non-Javadoc) 95 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#update(java.lang.Object) 96 */ 97 @Override 98 public void update(T record) { 99 this.getSession().update(record); 100 101 } 102 103 /* (non-Javadoc) 104 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#findById(java.io.Serializable) 105 */ 106 @Override 107 public T findById(Serializable id) { 108 return (T) this.getSession().get(entityClass, id); 109 } 110 111 /* (non-Javadoc) 112 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#find(java.lang.String, java.util.Map) 113 */ 114 @Override 115 public List<T> find(String hql, Map<String, Object> params) { 116 Query query = this.getSession().createQuery(hql); 117 query.setProperties(params); 118 return query.list(); 119 } 120 121 /* (non-Javadoc) 122 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#find(java.lang.String, int, int, java.util.Map) 123 */ 124 @Override 125 public Map<String, Object> find(String hql, int pageIndex, int pageSize, Map<String, Object> params) { 126 String hqlCount; 127 //通过给定的HQL语句查询全部条数 128 int i = hql.indexOf("from"); 129 if (i == 0) { 130 hqlCount = "select count(*) " + hql; 131 } else { 132 hqlCount = "select count(*) " + hql.substring(i); 133 } 134 135 Query query = this.getSession().createQuery(hql); 136 query.setProperties(params); 137 138 //index从0开始 139 query.setFirstResult((pageIndex - 1) * pageSize); 140 query.setMaxResults(pageSize); 141 142 int total = Integer.parseInt(this.getSession().createQuery(hqlCount).uniqueResult().toString()); 143 return this.createPageData(query.list(), pageIndex, pageSize, total); 144 } 145 146 /* (non-Javadoc) 147 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#find(int, int) 148 */ 149 @Override 150 public Map<String, Object> find(int pageIndex, int pageSize) { 151 Criteria criteria = this.getSession().createCriteria(entityClass); 152 153 //查询总数 154 criteria.setProjection(Projections.rowCount()); 155 int total = Integer.parseInt(criteria.uniqueResult().toString()); 156 criteria.setProjection(null); 157 158 criteria.setFirstResult((pageIndex - 1) * pageSize); 159 criteria.setMaxResults(pageSize); 160 return this.createPageData(criteria.list(), pageIndex, pageSize, total); 161 } 162 163 /* (non-Javadoc) 164 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#find(org.hibernate.criterion.DetachedCriteria) 165 */ 166 public List<T> find(DetachedCriteria detachedCriteria) { 167 return detachedCriteria.getExecutableCriteria(getSession()).list(); 168 } 169 170 /* (non-Javadoc) 171 * @see com.Elastic.StrutsDemo2.ivy.dao.IBaseDao#find(org.hibernate.criterion.DetachedCriteria, int, int) 172 */ 173 @Override 174 public Map<String, Object> find(DetachedCriteria detachedCriteria, int pageIndex, int pageSize) { 175 //查询总数 176 int total = Integer.parseInt(detachedCriteria.getExecutableCriteria(getSession()) 177 .setProjection(Projections.rowCount()) 178 .uniqueResult().toString()); 179 180 //分页查询 181 Criteria criteria = detachedCriteria.getExecutableCriteria(getSession()); 182 criteria.setFirstResult((pageIndex - 1) * pageSize); 183 criteria.setMaxResults(pageSize); 184 return this.createPageData(criteria.list(), pageIndex, pageSize, total); 185 } 186 }
c.具体业务接口 -- UserDao类
1 package com.Elastic.SpringDemo2.ivy.dao; 2 3 import com.Elastic.SpringDemo2.ivy.entity.User; 4 5 public interface UserDao extends IBaseDao<User> { 6 7 }
5.service包
a.业务接口 -- UserService
1 package com.Elastic.SpringDemo2.ivy.service; 2 3 import com.Elastic.SpringDemo2.ivy.entity.User; 4 5 public interface UserService { 6 User login(String name, String pass); 7 }
6.dao.impl包
a.接口实现类 -- UserDaoImpl
1 package com.Elastic.SpringDemo2.ivy.dao.impl; 2 3 import java.io.Serializable; 4 import java.util.List; 5 import java.util.Map; 6 7 import org.hibernate.Session; 8 import org.hibernate.criterion.DetachedCriteria; 9 10 import com.Elastic.SpringDemo2.ivy.dao.BaseDao; 11 import com.Elastic.SpringDemo2.ivy.dao.UserDao; 12 import com.Elastic.SpringDemo2.ivy.entity.User; 13 14 public class UserDaoImpl extends BaseDao<User> implements UserDao { 15 16 }
7.service.impl包
a.接口实现类 -- UserServiceImpl
1 package com.Elastic.SpringDemo2.ivy.dao.impl; 2 3 import com.Elastic.SpringDemo2.ivy.dao.UserDao; 4 import com.Elastic.SpringDemo2.ivy.entity.User; 5 import com.Elastic.SpringDemo2.ivy.service.UserService; 6 7 public class UserServiceImpl implements UserService { 8 9 private UserDao userDao; 10 11 public UserDao getUserDao() { 12 return userDao; 13 } 14 15 public void setUserDao(UserDao userDao) { 16 this.userDao = userDao; 17 } 18 19 @Override 20 public User login(String name, String pass) { 21 User user = userDao.findById(name); 22 if (null != user && user.getLoginPass().equals(pass)) { 23 return user; 24 } 25 return null; 26 } 27 }
b.异常抛出增强,接口实现类 -- UserServiceImpl
1 package com.Elastic.SpringDemo2.ivy.dao.impl; 2 3 import com.Elastic.SpringDemo2.ivy.dao.UserDao; 4 import com.Elastic.SpringDemo2.ivy.entity.User; 5 import com.Elastic.SpringDemo2.ivy.service.UserService; 6 7 public class UserServiceImpl implements UserService { 8 9 private UserDao userDao; 10 11 public UserDao getUserDao() { 12 return userDao; 13 } 14 15 public void setUserDao(UserDao userDao) { 16 this.userDao = userDao; 17 } 18 19 @Override 20 public User login(String name, String pass) { 21 User user = userDao.findById(name); 22 if (user.getLoginPass().equals(pass)) { 23 return user; 24 } 25 return null; 26 } 27 }
8.spring配置文件
a.后置增强 -- applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> 9 10 <!-- 使用IoC完成依赖注入 --> 11 <bean id="userDao" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserDaoImpl"></bean> 12 13 <bean id="userService" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserServiceImpl"> 14 <property name="userDao" ref="userDao"></property> 15 </bean> 16 17 <!-- 织入切面(方法执行前的操作) --> 18 <bean id="loggerBefore" class="com.Elastic.SpringDemo2.ivy.aop.LoggerBefore"></bean> 19 20 <!-- 使用切面 --> 21 <aop:config> 22 <!-- <aop:pointcut expression="execution(public com.Elastic.SpringDemo2.ivy.entity.User login(java.lang.String, java.lang.String))" id="pointcut"/> --> 23 <aop:pointcut expression="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))" id="pointcut"/> 24 <aop:advisor advice-ref="loggerBefore" pointcut-ref="pointcut"/> 25 </aop:config> 26 27 </beans>
b.后置增强 -- applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> 9 10 <!-- 使用IoC完成依赖注入 --> 11 <bean id="userDao" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserDaoImpl"></bean> 12 13 <bean id="userService" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserServiceImpl"> 14 <property name="userDao" ref="userDao"></property> 15 </bean> 16 17 <!-- 织入切面(方法执行前的操作) --> 18 <bean id="loggerBefore" class="com.Elastic.SpringDemo2.ivy.aop.LoggerBefore"></bean> 19 <bean id="loggerAfter" class="com.Elastic.SpringDemo2.ivy.aop.LoggerAfter"></bean> 20 21 <!-- 使用切面 --> 22 <aop:config> 23 <!-- <aop:pointcut expression="execution(public com.Elastic.SpringDemo2.ivy.entity.User login(java.lang.String, java.lang.String))" id="pointcut"/> --> 24 <aop:pointcut expression="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))" id="pointcut"/> 25 <aop:advisor advice-ref="loggerBefore" pointcut-ref="pointcut"/> 26 27 <aop:advisor advice-ref="loggerAfter" pointcut-ref="pointcut"/> 28 </aop:config> 29 30 </beans>
c.异常抛出增强 -- applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> 9 10 <!-- 使用IoC完成依赖注入 --> 11 <bean id="userDao" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserDaoImpl"></bean> 12 13 <bean id="userService" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserServiceImpl"> 14 <property name="userDao" ref="userDao"></property> 15 </bean> 16 17 <!-- 织入切面(方法执行前的操作) --> 18 <bean id="loggerBefore" class="com.Elastic.SpringDemo2.ivy.aop.LoggerBefore"></bean> 19 <bean id="loggerAfter" class="com.Elastic.SpringDemo2.ivy.aop.LoggerAfter"></bean> 20 <bean id="loggerException" class="com.Elastic.SpringDemo2.ivy.aop.LoggerException" ></bean> 21 22 23 <!-- 使用切面 --> 24 <aop:config> 25 <!-- <aop:pointcut expression="execution(public com.Elastic.SpringDemo2.ivy.entity.User login(java.lang.String, java.lang.String))" id="pointcut"/> --> 26 <aop:pointcut expression="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))" id="pointcut"/> 27 <aop:advisor advice-ref="loggerBefore" pointcut-ref="pointcut"/> 28 <aop:advisor advice-ref="loggerAfter" pointcut-ref="pointcut"/> 29 <aop:advisor advice-ref="loggerException" pointcut-ref="pointcut"/> 30 </aop:config> 31 32 </beans>
d.环绕增强 -- applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> 9 10 <!-- 使用IoC完成依赖注入 --> 11 <bean id="userDao" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserDaoImpl"></bean> 12 13 <bean id="userService" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserServiceImpl"> 14 <property name="userDao" ref="userDao"></property> 15 </bean> 16 17 <!-- 织入切面(方法执行前的操作) --> 18 <bean id="loggerBefore" class="com.Elastic.SpringDemo2.ivy.aop.LoggerBefore"></bean> 19 <bean id="loggerAfter" class="com.Elastic.SpringDemo2.ivy.aop.LoggerAfter"></bean> 20 <bean id="loggerException" class="com.Elastic.SpringDemo2.ivy.aop.LoggerException" ></bean> 21 <bean id="loggerArround" class="com.Elastic.SpringDemo2.ivy.aop.LoggerArround" ></bean> 22 23 24 <!-- 使用切面 --> 25 <aop:config> 26 <!-- <aop:pointcut expression="execution(public com.Elastic.SpringDemo2.ivy.entity.User login(java.lang.String, java.lang.String))" id="pointcut"/> --> 27 <aop:pointcut expression="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))" id="pointcut"/> 28 <!-- 环绕增强有顺序 --> 29 <aop:advisor advice-ref="loggerArround" pointcut-ref="pointcut"/> 30 <aop:advisor advice-ref="loggerBefore" pointcut-ref="pointcut"/> 31 <aop:advisor advice-ref="loggerAfter" pointcut-ref="pointcut"/> 32 <aop:advisor advice-ref="loggerException" pointcut-ref="pointcut"/> 33 34 </aop:config> 35 36 </beans>
e.使用注解 -- applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> 9 10 <!-- 使用IoC完成依赖注入 --> 11 <bean id="userDao" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserDaoImpl"></bean> 12 13 <bean id="userService" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserServiceImpl"> 14 <property name="userDao" ref="userDao"></property> 15 </bean> 16 17 <!-- 织入切面(方法执行前的操作) --> 18 <bean id="loggerBefore" class="com.Elastic.SpringDemo2.ivy.aop.LoggerBefore"></bean> 19 <bean id="loggerAfter" class="com.Elastic.SpringDemo2.ivy.aop.LoggerAfter"></bean> 20 <bean id="loggerException" class="com.Elastic.SpringDemo2.ivy.aop.LoggerException" ></bean> 21 <bean id="loggerArround" class="com.Elastic.SpringDemo2.ivy.aop.LoggerArround" ></bean> 22 23 <!-- 使用注解 --> 24 <bean id="loggerAop" class="com.Elastic.SpringDemo2.ivy.aop.LoggerAOP"></bean> 25 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 26 27 </beans>
f.使用schema -- applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> 9 10 <!-- 使用IoC完成依赖注入 --> 11 <bean id="userDao" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserDaoImpl"></bean> 12 13 <bean id="userService" class="com.Elastic.SpringDemo2.ivy.dao.impl.UserServiceImpl"> 14 <property name="userDao" ref="userDao"></property> 15 </bean> 16 17 <!-- 织入切面(方法执行前的操作) --> 18 <bean id="loggerBefore" class="com.Elastic.SpringDemo2.ivy.aop.LoggerBefore"></bean> 19 <bean id="loggerAfter" class="com.Elastic.SpringDemo2.ivy.aop.LoggerAfter"></bean> 20 <bean id="loggerException" class="com.Elastic.SpringDemo2.ivy.aop.LoggerException" ></bean> 21 <bean id="loggerArround" class="com.Elastic.SpringDemo2.ivy.aop.LoggerArround" ></bean> 22 23 24 <!-- 使用切面 --> 25 <aop:config> 26 <!-- 使用schema --> 27 <aop:aspect ref="loggerAop"> 28 <aop:pointcut expression="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))" id="pointcut"/> 29 <aop:before method="before" pointcut-ref="pointcut"/> 30 <aop:after-returning method="after" pointcut-ref="pointcut" returning="returnValue"/> 31 </aop:aspect> 32 </aop:config> 33 34 <!-- 使用注解 --> 35 <bean id="loggerAop" class="com.Elastic.SpringDemo2.ivy.aop.LoggerAOP"></bean> 36 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 37 38 </beans>
9.aop包
a.前置增强 -- LoggerBefore类
1 package com.Elastic.SpringDemo2.ivy.aop; 2 3 import java.lang.reflect.Method; 4 5 import org.springframework.aop.MethodBeforeAdvice; 6 7 public class LoggerBefore implements MethodBeforeAdvice{ 8 9 @Override 10 public void before(Method method, Object[] arg, Object target) 11 throws Throwable { 12 System.out.println("执行" + method.getName() + "之前:......"); 13 } 14 }
b.后置增强
1 package com.Elastic.SpringDemo2.ivy.aop; 2 3 import java.lang.reflect.Method; 4 5 import org.springframework.aop.AfterReturningAdvice; 6 7 public class LoggerAfter implements AfterReturningAdvice{ 8 9 @Override 10 public void afterReturning(Object returnValue, Method method, Object[] args, 11 Object target) throws Throwable { 12 System.out.println("方法返回值是:" + returnValue); 13 14 } 15 }
c.异常抛出增强
1 package com.Elastic.SpringDemo2.ivy.aop; 2 3 import java.lang.reflect.Method; 4 5 import org.springframework.aop.ThrowsAdvice; 6 7 public class LoggerException implements ThrowsAdvice { 8 public void afterThrowing(Method method, Object[] args, Object target, Throwable e) { 9 System.out.println("方法" + method.getName() + "调用时出现异常"); 10 } 11 }
d.环绕增强
1 package com.Elastic.SpringDemo2.ivy.aop; 2 3 import java.lang.reflect.Method; 4 5 import org.aopalliance.intercept.MethodInterceptor; 6 import org.aopalliance.intercept.MethodInvocation; 7 8 public class LoggerArround implements MethodInterceptor{ 9 10 @Override 11 public Object invoke(MethodInvocation invocation) throws Throwable { 12 System.out.println("方法执行前"); 13 Object result = invocation.proceed(); 14 System.out.println("方法执行后"); 15 return result; 16 } 17 }
e.注解
1 package com.Elastic.SpringDemo2.ivy.aop; 2 3 import org.aspectj.lang.JoinPoint; 4 import org.aspectj.lang.annotation.AfterReturning; 5 import org.aspectj.lang.annotation.Aspect; 6 import org.aspectj.lang.annotation.Before; 7 8 @Aspect(value="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))") 9 public class LoggerAOP { 10 11 //value 必填 12 @Before(value="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))") 13 public void before(JoinPoint point) { 14 System.out.println(point.getThis()); 15 System.out.println(point.getArgs()); 16 System.out.println(point.getTarget()); 17 18 //快照:副本 19 System.out.println(point.getSignature().getName()); 20 System.out.println("使用注解完成方法执行之前的拦截"); 21 } 22 23 @AfterReturning(value="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))",returning="returnValue") 24 //returning的值与参数的值一样 25 public void after(JoinPoint point, Object returnValue) { 26 System.out.println("方法执行之后......"); 27 System.out.println(point.getSignature()); 28 System.out.println(returnValue); 29 } 30 }
f.schema
1 package com.Elastic.SpringDemo2.ivy.aop; 2 3 import org.aspectj.lang.JoinPoint; 4 import org.aspectj.lang.annotation.AfterReturning; 5 import org.aspectj.lang.annotation.Aspect; 6 import org.aspectj.lang.annotation.Before; 7 8 //@Aspect(value="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))") 9 public class LoggerAOP { 10 11 //value 必填 12 // @Before(value="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))") 13 public void before(JoinPoint point) { 14 System.out.println(point.getThis()); 15 System.out.println(point.getArgs()); 16 System.out.println(point.getTarget()); 17 System.out.println(point.getSignature().getName()); 18 System.out.println("使用注解完成方法执行之前的拦截"); 19 } 20 21 // @AfterReturning(value="execution(* com.Elastic.SpringDemo2.ivy.service..*.*(..))",returning="returnValue") 22 //returning的值与参数的值一样 23 public void after(JoinPoint point, Object returnValue) { 24 System.out.println("方法执行之后......"); 25 System.out.println(point.getSignature()); 26 System.out.println(returnValue); 27 } 28 }
10.test包
a.前置增强 -- Test包
1 package com.Elastic.SpringDemo2.ivy.test; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 import com.Elastic.SpringDemo2.ivy.entity.User; 7 import com.Elastic.SpringDemo2.ivy.service.UserService; 8 9 public class Test { 10 11 public static void main(String[] args) { 12 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 13 UserService userService = (UserService)context.getBean("userService"); 14 User user = userService.login("admin", "123456"); 15 if (null == user) { 16 System.out.println("登录失败"); 17 } else { 18 System.out.println("登录成功"); 19 } 20 } 21 }
b.异常抛出增强 -- Test类
1 package com.Elastic.SpringDemo2.ivy.test; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 import com.Elastic.SpringDemo2.ivy.entity.User; 7 import com.Elastic.SpringDemo2.ivy.service.UserService; 8 9 public class Test { 10 11 public static void main(String[] args) { 12 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 13 UserService userService = (UserService)context.getBean("userService"); 14 User user = userService.login("admin11111", "123456"); 15 if (null == user) { 16 System.out.println("登录失败"); 17 } else { 18 System.out.println("登录成功"); 19 } 20 } 21 }
使用注解定义增强:
1.AspectJ(静态代理)是一个面向切面的框架,它扩展了Java语言,定义了AOP 语法,能够在编译期提供代码的织入
2.@AspectJ是AspectJ 5新增的功能,使用JDK 5.0 注解技术和正规的AspectJ切点表达式语言描述切面
3.Spring通过集成AspectJ实现了以注解的方式定义增强类,大大减少了配置文件中的工作量
a.使用@AspectJ,首先要保证所用的JDK 是5.0或以上版本
b.将Spring的asm 模块添加到类路径中,以处理@AspectJ中所描述的方法参数名
4.使用注解定义前置增强和后置增强实现日志功能
5.常用注解有@Aspect、@Before、@AfterReturning、@Around、@AfterThrowing、@After等
6.通过在配置文件中添加<aop:aspectj-autoproxy />元素,就可以启用对于@AspectJ注解的支持
7.定义最终增强
@AspectJ还提供了一种最终增强类型,无论方法抛出异常还是正常退出,该增强都会得到执行,类似于异常处理机制中finally块的作用,一般用于释放资源
使用Schema配置切面
POJO的方法配置成切面,所用标签包括<aop:aspect>、<aop:before>、<aop:after-returning>、<aop:around>、<aop:after-throwing>、<aop:after>等
Spring AOP and AspectJ AOP 有什么区别?
- AspectJ 静态代理(AOP框架在编译期生成AOP代理类)。在编译阶段将AspectJ(切面)织入到java字节码中,运行时就是增强的AOP对象。
- Spring AOP 动态代理。AOP框架不会修改字节码,每次运行时在内存中临时生成一个AOP对象,这个AOP对象包含目标对象的全部方法,在特定的切点做了增强处理,并回调原对象方法。