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开发步骤:

  1. 引入aop 相关 jar文件(aspectj 在spring之前,面向切面开发的公用组件)

aopalliance.jar

aspectjrt.jar

aspectjweaver.jar

spring-aop-3.2.5.RELEASE.ja

  1. 引入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();
}