Spring 注解方式实现aop编程 (七)
Aop编程
public void add(User user) {
Session session = null;
Transaction trans = null;
try {
session = HibernateSessionFactoryUtils.getSession(); //【关注点代码】
trans = session.beginTransaction(); //【关注点代码】
session.save(user); // 业务
trans.commit(); //【关注点代码】
} catch (Exception e) {
e.printStackTrace();
if(trans != null){
trans.rollback();
}
} finally{
HibernateSessionFactoryUtils.closeSession(session);
}
}
简化代码,只要关注业务
主要是分离业务代码与关注点代码!关注点代码,写一次,在执行业务代码时候动态植入关注点代码!
自己实现aop编程
/**
* Created by Matrix42 on 2017/5/8.
*/
public interface IUserDao {
public void save();
}
/**
* Created by Matrix42 on 2017/5/8.
*/
import org.springframework.stereotype.Component;
/**
* 1. 面向过程的分离
* 2. 对象化分离
*/
@Component("user")
public class UserDao implements IUserDao{
public void save(){
System.out.println("保存...");
}
}
/**
* Created by Matrix42 on 2017/5/8.
*/
//重复代码
@Component("aop")
public class TransactionAop {
public void beginTransaction(){
System.out.println("开启事务...");
}
public void commit(){
System.out.println("提交事务...");
}
}
/**
* Created by Matrix42 on 2017/5/8.
*/
//代理工厂
@Component
public class ProxyFactory {
/**
*
* @param target 目标对象
* @param aop 给目标对象动态注入的重复的代码(关注点代码)
* @return
*/
public Object getProxyInstance(final Object target, final TransactionAop aop){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
aop.beginTransaction();
Object result = method.invoke(target,args);
aop.commit();
return result;
}
}
);
}
}
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Created by Matrix42 on 2017/5/8.
*/
public class UserDaoTest {
private ApplicationContext ac = new AnnotationConfigApplicationContext("my_aop");
@Test
public void testAop(){
ProxyFactory proxyFactory = ac.getBean(ProxyFactory.class);
UserDao dao = ac.getBean(UserDao.class);
TransactionAop transactionAop = ac.getBean(TransactionAop.class);
IUserDao userDao = (IUserDao) proxyFactory.getProxyInstance(dao,transactionAop);
userDao.save();
}
}
AOP编程, 注解方式
Aop编程:关注点代码与业务代码分离!(jdk/cglib代理)
关注点:重复执行的代码, 也叫关注点代码!
切面:关注点代码形成的类,就叫做切面 springAop编程,也叫面向切面编程!
Aop: Aspect Object Programming 面向切面编程!
举例,哪些是切面? 事务,权限控制, 日志…
切入点表达式:拦截方法,给方法所在的类,生成代理对象!
Spring在初始化容器的时候,会根据切入点表达式的规则,会符合拦截规则的方法所在的类生成代理对象!
使用Aop开发步骤:
- 引入aop 相关 jar文件(aspectj 在spring之前,面向切面开发的公用组件)
aopalliance.jar
aspectjrt.jar
aspectjweaver.jar
spring-aop-3.2.5.RELEASE.ja
- 引入aop名称空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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="com.matrix42.pac></context:component-scan>
<!-- 开启aop注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
注解详解
@Aspect 指定一个类为切面类(切面类也需要实例化)(切面类中的方法,也叫做通知)
@Before 前置通知 【在执行目标对象方法之前执行】
@After 后置通知 【在执行目标对象方法之后执行】
@AfterReturning 返回后通知 【在执行目标对象方法结束后执行, 出现异常不执行】
@AfterThrowing 异常通知 【在执行目标对象方法出现异常时候执行】
@Around 环绕通知 【环绕目标方法执行】
@Pointcut 定义一个切入点表达式变量 (后面使用这个切入点表达式的时候,直接引用方法名即可)
// 定义一个切入点表达式变量 (后面使用这个切入点表达式的时候,直接引用方法名即可)
@Pointcut("execution(* cn.itcast.e_aop_anno.UserDao.*(..))")
public void pointcut_(){
}
//@Around("pointcut_()")
@Test
public void testApp() throws Exception {
// springIOC容器中获取对象,用接口接收!
//IUserDao userDao = (IUserDao) ac.getBean("userDao");
//System.out.println(userDao.getClass());
//userDao.save();
/ springIOC容器中获取对象,用实现接收? 报错!!!!!!!!!
/*
* java.lang.ClassCastException:
* $Proxy13 cannot be cast to cn.itcast.e_aop_anno.UserDao
*/
// 总结:在spring的aop编程中,符合切入点表达式的目标类, 如果目标对象有实现接口,从容器获取对象的时候,一定要通过接口接收!
// 否则,包类型转换错误!
UserDao userDao = (UserDao) ac.getBean("userDao");
System.out.println(userDao.getClass());
userDao.save();
}