AOP
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑代码封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
AOP核心概念
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
实例
创建实体
/**
* UserInfo 实体
*/
public class UserInfo implements Serializable {
private Integer user_id;
private String user_name;
public Integer getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
}
创建Dao
/**
* Dao层接口
*/
public interface IUserInfoMapper {
//添加用户
public int addUser(UserInfo info);
}
创建DaoImpl
public int addUser(UserInfo info) {
System.out.println("add success!");
return 0;
}
创建Serviec
public interface IUserInfoService {
//添加用户
public int addUser(UserInfo info);
}
创建ServiecImpl
//注入Dao层对象
private IUserInfoMapper iUserInfoMapper;
public IUserInfoMapper getiUserInfoMapper() {
return iUserInfoMapper;
}
public void setiUserInfoMapper(IUserInfoMapper iUserInfoMapper) {
this.iUserInfoMapper = iUserInfoMapper;
}
@Override
public int addUser(UserInfo info) {
int count = iUserInfoMapper.addUser(info);
return count;
}
编写增强类
/**
* 编码方式实现AOP
*/
public class MyAdvice implements MethodBeforeAdvice, AfterReturningAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("============前置增强:日志处理等操作========================");
}
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("============后置增强:事务处理等操作=========================");
}
}
编写applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--声明Daobean bean的注入注入的都是实现类-->
<bean id="iUserInfoMapper" class="spring.mapper.impl.IUserInfoMapperImpl"></bean>
<!--声明Service-->
<bean id="iUserInfoService" class="spring.service.impl.IUserInfoServiceImpl">
<!--setter方法怎么注入:找到Name属性值,将属性值的开头改为大写,然后前缀加上setIUserInfoMapper-->
<property name="iUserInfoMapper" ref="iUserInfoMapper"></property>
</bean>
<!--配置增强-->
<aop:config>
<!--切点-->
<aop:pointcut id="pointcut" expression="execution(* *..service.*.*(..))"/>
<!--织入 ref指向增强类的bean-->
<aop:aspect ref="myadvice">
<!--method增强方法-->
<aop:before method="before" pointcut-ref="pointcut" ></aop:before>
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
</aop:aspect>
</aop:config>
</beans>
编写测试类
@Test
public void aopTest()
{
//步骤一:加载applicationContext.xml文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//步骤二:调用Bean
IUserInfoService iUserInfoService = (IUserInfoService)ctx.getBean("iUserInfoService");
iUserInfoService.addUser(new UserInfo());
}
结果
扩展实例2
编写实体User类
/**
* UserInfo 实体
*/
public class UserInfo implements Serializable {
private Integer user_id;
private String user_name;
public Integer getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
}
编写student
public class Student {
private Integer stu_id;
private String stu_name;
public Student(Integer stu_id, String stu_name) {
this.stu_id = stu_id;
this.stu_name = stu_name;
}
public Student() {
}
public Integer getStu_id() {
return stu_id;
}
public void setStu_id(Integer stu_id) {
this.stu_id = stu_id;
}
public String getStu_name() {
return stu_name;
}
public void setStu_name(String stu_name) {
this.stu_name = stu_name;
}
@Override
public String toString() {
return "Student{" +
"stu_id=" + stu_id +
", stu_name='" + stu_name + '\'' +
'}';
}
}
编写applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--声明Daobean bean的注入注入的都是实现类-->
<bean id="iUserInfoMapper" class="cn.spring.mapper.impl.IUserInfoMapperImpl"></bean>
<!--声明Service-->
<bean id="iUserInfoService" class="cn.spring.service.impl.IUserInfoServiceImpl">
<!--setter方法怎么注入:找到Name属性值,将属性值的开头改为大写,然后前缀加上setIUserInfoMapper-->
<property name="iUserInfoMapper" ref="iUserInfoMapper"></property>
</bean>
<!--基于Setter注入-->
<!--<bean id="student" class="cn.spring.di.Student">
<property name="stu_id" value="1"></property>
<property name="stu_name" value="张三"></property>
</bean>-->
<!--基于构造注入-->
<bean id="student" class="cn.spring.di.Student">
<!--构造注入: name代表构造内参数的名字 value代表参数值 type代表参数数据类型 index参数下标-->
<constructor-arg value="2" type="java.lang.Integer" index="0"></constructor-arg>
<constructor-arg value="李四" type="java.lang.String" index="1"></constructor-arg>
</bean>
编写测试类
@Test
public void diTest()
{
//步骤一:加载applicationContext.xml文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//步骤二:调用Bean
Student student = (Student)ctx.getBean("student");
System.out.println(student.toString());
}
结果