spring笔记AOP

                      面向方面编程(Spring AOP)
分散关注:
        将通用需求功能从不相关类中分离出来;同时,能够使得很多类共享一个行为,一旦行为发生变化,不必修改很多类,只要修改这个行为就可以。

AOP就是这种实现分散关注的编程方法,它将”关注”封装在”方面”中

AOP是什么?
AOP 是OOP的延续,是Aspect Oriented Programming 的缩写,意思是面向方面编程。他实际上是Gof设计模式的延续,主要是为了解耦。它是一种编程技术,用来在系统中提升业务分离。AOP将服务模块化,并把它们声明式的应用在需要的地方。从点到点的思维转向点到面的思维,这就是面向切面编程。

优点: AOP以“动态织入”的方式大大提高了应用开发效率,有效的降低软件的复杂性,代码的清晰性、模块化、可测试性方面也会取得很好的提升。

AOP的基本术语:

切面(Aspect):要实现的交叉功能。它是应用系统模块化的一个切面或领域。就是说你附加些撒子功能

连接点(JoinPoint):是应用程序执行过程中插入切面的地点。这个地方可以是方法调用,异常抛出,修改字段。 在Spring中,连接点就特指对某个方法的调用。连接点就无非方法

通知(Advice):通知是指某个切入点要执行的代码。就是你要让你的方法干些什么事

切入点(pointcut):定义通知应该应用在那些连接点。你附加的功能加到那个方法

目标对象(target):目标对象是被通知的对象。 就是你要附加功能的类嘛!

织入(weaving):切面应用到目标对象从而创建一个新的代理对象的过程


Spring 的AOP实现:

第一:创建通知

通知就是包含了切面逻辑的JavaBean

前置通知:(MethodBeforeAdvice)接口。
before(Method method, Object[] args, Object target) 这个方法有三个参数,第一个参数是个Method目标方法的属性。 
Object[] args对象数组,它保存了调用目标方法时所传递的参数
Object target 保存目标方法所属的对象。
前置通知没有返回值,唯一能阻止目标方法就是抛出异常

后置通知:(AfterReturningAdvice)接口,afterReturning(Object obj,Method method,Object[] arg1,Object arg2) 这个方法有四个参数
Object obj 保存目标方法的返回结果对象
Method method 目标方法的属性
Object[] arg1 调用目标方法所调用的方法
Object arg2目标方法所属的对象

第二 :定义切入点

Advice 与 Advisor 的区别?
Advice :通知,就是切入点要执行的代码
Adivsor :通知和切入点组合到一个对象

第三:使用ProxyFactoryBean

他主要是用来创建代理对象,那么为什么要创建代理对象啦!
因为我们AOP是用到的,动态代理模式,实现动态代理就必须 代理对象 和 目标对象 他们实现同一个接口,就是吧添加的功能分化出来实现

要我说:理解AOP 就要好好理解下动态代理模式,理解这其中的原理,方法,方法所要传的参数,配置xml文件无非把参数传入,描述他们之间的关系

这其中的属性有:
Target 代理目标对象
ProxyInterface 代理应该实现的接口
InterceptorNames :需要应用到目标对象上的通知Bean名字

自动代理:(BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator)

理论知识完!!!!!!!!!













                           代码演示部分!



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans> 
    <!-- 目标对象,相当于面包  就是我们的目标对象 target-->
    <bean id="bankService" class="com.lovo.BankServiceImpl"></bean>
    <!-- 定义通知,相当于牛肉  就是我们的通知Advice-->
    <bean id="logAdvice" class="com.lovo.LogAdvice"></bean>
   
    <!-- 定义一个切入点实现,相当于一个面包师,他知道在哪里添加牛肉   Advisor它是把通知和切入点组合到一个对象中-->
    <bean id="logAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="logAdvice"></property>
        <property name="mappedNames">
               <list>
                   <value>zz</value>
                   <value>save</value>
               </list>
        </property>
    </bean>

     <!--
     <bean id="logAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
         <property name="advice" ref="logAdvice"></property>
         <property name="pattern" value=".*zz"></property>
     </bean>
     -->
    <!-- 制作汉堡,放入面包,牛肉,返回汉堡,而不是汉堡工厂自己 -->
    <bean id="bankProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="bankService"></property>
        <property name="interceptorNames">
            <list>
                <value>logAdvisor</value>
             </list>
        </property>
        <property name="interfaces">
             <list>
                 <value>com.lovo.BankService</value>
             </list>
        </property>
    </bean>
   
    <!-- 定义学生目标对象 -->
    <bean id="student" class="com.lovo.s.StudentServieImpl"></bean>
    <bean id="studentProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="student"></property>
        <property name="interceptorNames">
            <value>logAdvisor</value>
        </property>
        <property name="interfaces">
            <value>com.lovo.s.StudentService</value>
        </property>
    </bean>
</beans>


自动代理部分:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans> 

    <!-- 目标bean对象 -->
    <bean id="bankService" class="com.lovo.BankServiceImpl"></bean>
    <bean id="studentService" class="com.lovo.s.StudentServieImpl"></bean>
   
    <!-- 通知,具体切面的实现 -->
    <bean id="logAdvice" class="com.lovo.LogAdvice"></bean>
  
    <!-- 一个advisor,定义了切入点,也就是在那些链接点上应用通知 -->
    <bean id="logAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
       <property name="advice" ref="logAdvice"></property>
       <property name="mappedNames">
           <list>
                <value>zz</value>
                <value>save</value>
           </list>
       </property>
    </bean>
   
    <!-- 定义自动代理,spring会自动寻找符合条件的bean,然后封装为代理对象返回,
        使用getBean("xxxService"); 返回的就是一个代理对象。
     -->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
             <list>
                 <value>*Service</value>
             </list>
        </property>
        <property name="interceptorNames">
              <list>
                 <value>logAdvisor</value>
              </list>
        </property>
    </bean>

</beans>



回调?
回调在hibernate 与 spring结合中,用到的非常多。
列举一个简单的回调实例:
AhibernateCallback 接口:
public interface AHibernateCallback {
    public Object doInHibernate(Session session);
}


AhibernateTemplate 类:    这里用到了 模板模式,简单理解就是把不变的与可变的分离。  即所谓的开、闭原则
public  class AHibernateTemplate {
    private SessionFactory sessionFactory;
   
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

public Object query(AHibernateCallback action){
Session session = this.sessionFactory.openSession();
        Object obj = action.doInHibernate(session);
session.close();
return obj;
}

}


UserDao 类:
ublic class UserDao {
     private AHibernateTemplate template;

public void setTemplate(AHibernateTemplate template) {
this.template = template;
}
    
    public Object getUser(final int id){
    return this.template.query(new AHibernateCallback(){

public Object doInHibernate(Session session) {
                String hql = "from User u where u.id = ?";
                return  session.createQuery(hql).setParameter(0, id).uniqueResult();
}});
}


Test类:
public class Test {
   public static void main(String[] args) {
   ApplicationContext ctx = new ClassPathXmlApplicationContext("s6.xml");
   UserDao dao =  (UserDao) ctx.getBean("userDao");
       User u = (User) dao.getUser(2);
       System.out.println(u.getUserName());
   }
}


JAVA的CALLBACK通过接口来实现。  
  例:  
  1.class   A,class   B  
  2.class   A实现接口operate  
  3.class   B拥有一个参数为operate接口类型的函数test(operate   o)  
  4.class   A运行时调用class   B中test函数,以自身传入参数  
  5.class   B已取得A,就可以随时回调A所实现的operate接口中的方法

你可能感兴趣的:(设计模式,spring,AOP,编程,bean)