AOP-动态代理-代码

AOP

…AOP(Aspect Oriented Programming),面向切面编程,是面向对象编程OOP的一种补充.面向对象编程是从静态角度考虑程序的结构,而面向切面编程是从动态角度考虑程序运行过程,AOP 底层,就是采用动态代理模式实现的。采用了两种代理:JDK 的动态代理,与 CGLIB的动态代理。
…动态代理的意义在于生成一个占位(又称代理对象, 来代理真实对象,从而控制真实对象的访问。

代理模式

…假设这样一个个场景,你的公司是家软件公司,你是软件工程师。客户带着需求去找公司显然不会直接和你谈,而是去找商务谈,此时客户会认为商务就代表公司。显然客户是通过商务去访问软件工程师的,那么商务(代理对象)的意义在于什么呢?商务可以进行谈判,比如项目启动前的商务谈判 软件的价格、交付、进度的时间节点等,或者项目完成后的商务追讨应收账款等。商务也有可能在开发软件之前谈判失败,此时商务就会根据公司规 去结束和客户的合作关系,这些都不用软件工程师来处理。
…因此,代理的作用就是,在真实对象访问之前或者之后加入对应的逻辑,或者根据其规则控制是否使用真实对象,显然在这个例子里商务控制了客户对软件工程师的访问。
…经过上面的论述,我知道商务和软件工程师是代理和被代理的关系 客户是经过商务去访问软件工程师的。此时客户就是程序中的调用者,商务就是代理对象 软件工程师就是真实对象。我 需要在调用者调用对象之前产生 个代理对象,而这个代理对象需要和真实对象建立代理关系,所以代理必须分为两个步骤代理:1)对象和真实对象建立代理关系;2)实现代理对象的代理逻辑方法
…Java 中有多种动态代理技术,目前 Spring 常用 JDK、CGLIB 。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
//通过后置通知来进行举例
//定义接口
public interface ISomeService {
  void doFirst();
  String doSecond();
}
public class SomeServiceImpl implements ISomeService{

	public void doFirst(){
		System.out.println("执行dofirst");
}
	public String doSecond(){
		System.out.println("执行doSecond");
		return "abcde";
}
}
public class MyAfterReturningAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object arg0,
			Method arg1, Object[] arg2, Object arg3) throws Throwable {

		System.out.println("执行后置方法");
	}

}
<?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:tx="http://www.springframework.org/schema/tx"
    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
        ">
        
    <bean id="someService" class="com.spring.aop02.SomeServiceImpl"/>
    <bean id="myAdice" class="com.spring.aop02.MyAfterReturningAdvice"/>
    
    <bean id="ServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    	<property name="target" ref="someService"/>
    	<property name="interceptorNames" value="myAdice"/>
    </bean>

        
</beans>
@Test
	public void test01() {
	ApplicationContext ctx=new ClassPathXmlApplicationContext("com/spring/aop02/applicationContext.xml");
		      ISomeService hello=(ISomeService) ctx.getBean("ServiceProxy");
		      hello.doFirst();
				System.out.println("=============");
		     String result= hello.doSecond();
				System.out.println(result);	}}

结果:
在这里插入图片描述而这个时候因为是接口,Spring默认动态代理是JDK
在这里插入图片描述

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

JDK 动态代理必须提供接口才能使用,有些不能提供接口的环境中,只能采用其他方技术, 比如 CGLIB 动态代理。

只需要修改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:tx="http://www.springframework.org/schema/tx"
    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
        ">
    <!-- 注册目标对象 -->    
    <bean id="someService" class="com.spring.aop03.SomeServiceImpl"/>
        <!-- 注册切面:通知 -->    
    <bean id="myAdice" class="com.spring.aop03.MyAfterReturningAdvice"/>
        <!-- 生成代理对象 -->    
    <bean id="ServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    	<property name="target" ref="someService"/>
    	<property name="interceptorNames" value="myAdice"/>
    	<!--在这里添加下列代码即可-->
    	<!--第一种-->
    	<property name="proxyTargetClass" value="true"/>
    	
    </bean>

        
</beans>

第二种:

   <property name="optimize" value="true"/>

在这里插入图片描述运行结果一样,但代理对象是CGLIB
在这里插入图片描述

3、如果目标对象没有实现了接口,必须采用CGLIB
public class SomeService {
public void dofirst(){
System.out.println("输出dofirst()方法");
}
public void doSecond(){

}
}
public class MyAfterReturningAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object arg0,
			Method arg1, Object[] arg2, Object arg3) throws Throwable {

		System.out.println("执行后置方法");
	}
}
<?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:tx="http://www.springframework.org/schema/tx"
    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">
        
      <!-- 注册目标对象 -->    
    <bean id="someService" class="com.spring.aop01.SomeService"/>
        <!-- 注册切面:通知 -->    
    <bean id="myAdice" class="com.spring.aop01.MyAfterReturningAdvice"/>
        <!-- 生成代理对象 -->    
    <bean id="ServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
     <property name="target" ref="someService"/>
     <property name="interceptorNames" value="myAdice"/>
             
    </bean>
</beans>

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值