Spring AOP

一、spring(春天)核心之 aop(重点)

aop:Aspect Oriented Programming 面向切面编程 ,是一种思想。
oop: Object Orinted programming 面向对象编程 ,是一种思想。
AOP可以说是OOP的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,在类的层次上进行抽取。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

总结:
oop:纵向抽取
好处:
1)提高可重用性
2)提高可扩展和可维护
3)多态
aop:横向向抽取
好处:
1)提高可重用性
2)提高可扩展和可维护

二、aop怎么玩?

1.aop底层原理:动态代理技术
2. jdk动态代理和cglib动态代理
代理========>经纪人、中介

三、动态代理(重点)

黑客入侵

1)jdk黑客: 只能入侵实现接口的对象。 针对接口实现类
jdk接口:InvocationHandler
==>JDK动态代理技术
## jdk动态代理(只能动态代理有接口的类)
1、先创建一个接口

public interface UserDao {
    int add(int a, int b);
}

2、实现接口

public class UserDaoImpl implements UserDao {
    @Override
    public int add(int a, int b) {
        System.out.println("调用UserDaoImpl的add方法");
        return a+b;
        
    }

}

3、创建JdkHk实现InvocationHandler接口

public class JdkHk implements InvocationHandler{
     //目标对象
    private Object  target;
    public JdkHk() {
    }
    //有参构造,传入参数
    public JdkHk(UserDao userDao) {
        this.target=userDao;
    }
    /**
     * 黑客类入侵的方法
     * proxy:代理对象
     * method:入侵的目标的方法
     * args:入侵的目标的方法的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("1、鉴权成功");
        
        //干坏事
        args[0]=11;
        args[1]=22;
        //调用目标方法
        Object result = method.invoke(target, args);
        System.out.println("2、保存处理日志成功");
        return result;
    }
    public Object getTarget() {
        return target;
    }
    public void setTarget(Object target) {
        this.target = target;
    }
}

4、测试类

public class Test01 {
    public static void main(String[] args) {
        //客户端---调用目标类(UserDaoImpl)的目标方法add方法
//        UserDao userDao = new UserDaoImpl();
//        int result = userDao.add(3, 5);
//        System.out.println("result==>:"+result);

        //目标对象
        UserDao targert = new UserDaoImpl();
        //黑客对象
        JdkHk jdkHk = new JdkHk(targert);
        //代理对象
        /*
         * loader             类加载器
         *          ClassLoader.getSystemClassLoader() 获取当前程序的类加载器
         * interfaces       目标的实现的接口class
         * h                     invocationHandler对象--黑客对象
         * 字节码拼接技术
         */
        UserDao userDao = (UserDao) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {UserDao.class}, jdkHk);
        //客户端
        int result = userDao.add(45, 5);
        System.out.println("result==>"+result); 
    }
}

2)spring黑客:针对类(aspect包—spring提供的)
aopalliance: MethodInteceptor 当类实现接口内部用的jdk黑客 如果类没有实现接口 使用cglib动态代理
==>可以使用JDK动态代理(实现接口类) 也可以使用Cglib动态代理(类或实现接口类)
1、创建一个不实现接口的类

public class UserDaoImpl2 {
    public int add(int a, int b) {
        System.out.println("调用UserDaoImpl的add方法");
        return a+b;
     }
}

2、创建springHk类实现MethodInteceptor 接口

public class SpringHk  implements MethodInterceptor{
    /*
     * invocation  : 目标对象的目标方法  
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("1.鉴权");
        //调用目标方法
        Object result = invocation.proceed();
        System.out.println("1.日志留痕");
        return result;
    }

}

3、测试类(这里通过依赖注入的方式来创建对象,需要配置文件spring-beans.xml)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-beans.xml")
public class SpringHkTest {

    @Autowired//默认按类型注入,通过@Qualifier修改为按名称注入
    @Qualifier("userDaoProxy")
    private UserDaoImpl2 userDao;//cglib
    
    
    @Autowired//默认按类型注入,通过@Qualifier修改为按名称注入
    @Qualifier("userDaoProxy2")
    private UserDaoImpl userDao2;//cglib
    @Test
    public void test01() {
        //目标没有实现接口
        System.out.println(userDao.add(3, 5));
        
        System.out.println(userDao2.add(3, 5));
    }
}

spring-beans.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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	<!--1.目标对象  -->
	<bean id="userDao" class="com.cc.dao.impl.UserDaoImpl2"></bean>
	<bean id="userDaoInter" class="com.cc.dao.impl.UserDaoImpl"></bean>
    
	<!--2.spring 黑客对象  -->
	<bean id="springHk" class="com.cc.proxy.SpringHk">
	</bean>
	
	<bean id="jdkHk" class="com.cc.proxy.JdkHk">
		<!-- <constructor-arg name="target" ref="userDaoInter"></constructor-arg> -->
    </bean>
	
	<!--3.代理对象  :Cglib动态代理  -->
	<bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
	 <!--   3.1 目标对象 -->
	   <property name="target" ref="userDao"></property>
	  <!--  3.2 spring 黑客对象 -->
	   <property name="interceptorNames">
	       <array>
	           <value>springHk</value>
	       </array>
	   </property>
	   
	</bean>
	
	  <!-- JDK动态代理 -->
	<bean id="userDaoProxy2" class="org.springframework.aop.framework.ProxyFactoryBean">
       <!--   3.2 目标对象 -->
       <property name="proxyInterfaces" value="com.cc.dao.UserDao"></property>
        
     <!--   3.1 目标对象 -->
       <property name="target" ref="userDaoInter"></property>
       
      <!--  3.2 spring 黑客对象 -->
       <property name="interceptorNames">
           <array>
               <value>springHk</value>
           </array>
       </property>
       
    </bean> 
</beans>

四、aop的术语

1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象
7、植入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

aop:将对象的目标方法通过动态代理技术进行植入增强,从而达到
增强方法的目的

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值