spring-03-2

有问题可以问我,spring前面的几篇文章不清不楚,我整体过一遍再重新写

AOP联盟通知类型

advice

  • 回忆一下什么是advice?
  • 要是不记得的话可以看看我spring-03-1里面例子的那个图片,说白了,advice里面就是指向的增强功能的代码内容

AOP联盟为通知Advice定义了org.aopalliance.aop.Advice这个类,且Spring按照通知Advice在目标类方法的连接点位置,可以分为5类:

  • 前置通知 org.springframework.aop.MethodBeforeAdvice
  • 在目标方法执行前实施增强
  • 后置通知 org.springframework.aop.AfterReturningAdvice
  • 在目标方法执行后实施增强
  • 环绕通知 org.springframework.aop.MethodIntercepter
  • 在目标方法执行前后实施增强
  • 异常抛出通知 org.springframework.aop.ThrowsAdvice
  • 在方法抛出异常后实施增强
  • 引介通知 org.springframework.aop.IntroductionInterceptor
  • 在目标类中添加一些新的方法和属性

spring AOP采用半自动代理

什么是代理半自动呢?

  • 代理半自动是指,我们不用手动去创建代理对象,我们直接在xml中配置代理对象,然后从容器中获取就好了

配置代理的注意事项:

  • 必须有两个属性,一个切面类对象,一个目标类对象,接口有就写没有就不写.

  • 半自动代理默认使用的是jdk的动态代理方式,有接口一定是jdk的动态代理,没有接口就使用cglib的代理方式.

  • 可以通过在配置文件中强制使用cglib增强代理,在spring配置的bean中添加这样一行: ,这样,就会只使用cglib增强代理了

  • 当你想使用jdk的动态代理的时候,那就写上接口,并且不要强制使用cglib增强代理,在源码中,接口和切面类(准确的说是增强代码所在的类的对象)那个属性的定义其实是一个list集合,但是只有一个的时候我们可以直接写的value,多个接口的时候就要写成集合了
    案例:

		第一步: 导入jar包(idea创建spring项目都会自动导入不用管):
			四个核心包(beans,context,core,expression)
			一个日志包(logging)
			AOP联盟包(定义了规范,里面都是接口,com.springsource.org.aopalliance.jar)
			spring-aop包(aop联盟的实现,spring-aop-3.2.0.RELEASE.jar)
		
		第二步: 创建目标类
		public class UserService {
		    public void addUser() {
		        System.out.println("添加了一个用户!");
		    }
		}
		
		第三步: 创建切面类
		public class MyAspect implements MethodInterceptor {
		    @Override
		    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		        //拦截方法
		
		        System.out.println("开启事务");
		        //放行
		        Object obj = methodInvocation.proceed();
		        System.out.println("结束事务");
		        System.out.println("已成功拦截,切入点前开启事务,切入点后提交事务");
		
		        return obj;
		    }
		}
		
		第四步: spring配置
		<?xml version="1.0" encoding="utf-8" ?>
		<beans xmlns="http://www.springframework.org/schema/beans"
		       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		       xsi:schemaLocation="http://www.springframework.org/schema/beans
		                        http://www.springframework.org/schema/beans/spring-beans.xsd">
		
		    <!--配置userservice-->
		    <bean id="userService" class="UserService">
		        <property name="name" value="樊磊"></property>
		    </bean>
		
		    <!--配置一个切面类对象-->
		    <bean id="myAspect" class="MyAspect">
		
		    </bean>
		    <!--配置代理,有接口就采用jdk动态代理,没有就采用cglib代理,默认使用jdk动态代理-->
		    <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		        <!--接口-->
		        <!--<property name="interfaces" value="接口全路径"></property>-->
		
		        <!--目标对象-->
		        <property name="target" ref="userService"></property>
		
		        <!--切面类对象 注意这里是value,不是ref,和目标对象区分一下子-->
		        <property name="interceptorNames" value="myAspect"></property>
		    </bean>
		</beans>
		
		第五步: 测试类
		public class Test {
		    public static void main(String[] args) {
		        //获取spring容器中的代理对象
		        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		
		        UserService userService = (UserService) context.getBean("serviceProxy");
		
		        //调用方法
				//此处的userService为代理对象
		        userService.addUser();
		    }
		}

spring AOP采用全自动代理

这个就是说,我们本来是需要通过代理实现目标类获取功能增强,但是现在直接让增强的功能和目标类相连接,直接跳过代理这个东西,但是切面类这些的还是要自己整哈.

什么是全自动织入

  • 结合我spring-03-1那篇博客里的图,织入(weaving)就是将advice通过代理类添加到目标类中的过程.

  • 全自动织入,emm,可以理解为我们相对于半自动代理来说不需要配置代理类,直接让切面里的通知送到切入点进行结合.

结合案例说明xml配置中expression表达式的写法

  1. **<aop:config proxy-target-class=“true”>**这表示使用的是cglib代理,值为false或者不写表示使用的是jdk的代理(基于接口的时候使用).

  2. execution中参数的意义:以execution(* example1.service.*.*(..))为例.

  • 括号里第一个*,表示任意返回值,即不管方法的返回值是int还是String或者其它类型都会被过滤,也可以指定为int或者其他类型.

  • 括号中的example1.service表示包名,表示切入点在这个包下,同时注意这里的包名是src下面的报名,即如果是src.package1.package2.targetClass的话,就写成package1.package2.

  • 括号里的第二个*,也就是example1.service.*的这个*号表示该包下面的所有类都会被过滤,被当作切入点,也可以指定类名,例如:

  • example1.service.fan,这就表示只有该包下的fan的这个类会被过滤和增强.

  • example1.service..fan,就只是多了一个.,这表示service这个包及其子包下的fan这个类都会被过滤

  • 括号里的第三个*,也就是example1.service.*.*中的第二个*,它表示类下面的所有方法都会被过滤,被当作切入点,也可以指定某个方法或者以某个单词开头的方法作为切入点,例如:
  • example1.service.fan.test表示只有fan这个类下面的test()方法会被过滤.

  • example1.service.fan.user*表示fan这个类下面所有以user开头的方法都会被过滤

  • example1.service..fan.user*表示service及其子包下面的fan这个类下面的user开头的方法都会被过滤

  • 括号中的(..),表示方法的参数为任意个数,任意类型参数都会被过滤,也可以自己指定,例如:
  • ()什么都不写表示只过滤空参的方法.

  • (*)表示只过滤一个参数的方法,参数可以为任意类型

  • (*,*)表示只过滤两个参数的方法,多个参数用,隔开即可

  • (*,int)表示只过滤两个参数且第二个参数为int类型的方法,多个参数用,隔开即可

案例:

		第一步:
			导入jar包: aspectjweaverjar.版本尽量高一点吧
		
		第二步:
			切面类: 注意此时一定要继承接口而且我们这里继承的是aop联盟的接口不是cglib的接口
			import org.aopalliance.intercept.MethodInterceptor;
			import org.aopalliance.intercept.MethodInvocation;
			
			public class MyAspect implements MethodInterceptor {
			
			    @Override
			    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
			        System.out.println("开启事务");
			
			        //放行
			        Object obj = methodInvocation.proceed();
			        System.out.println("结束事务");
			
			        return obj;
			    }
			}
		
		第三步:
			目标类
			public class UserService {
					    public void addUser() {
					        System.out.println("添加了一个用户!");
					    }
					}
		
		第四步:
			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: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/aop
		                        http://www.springframework.org/schema/aop/spring-aop.xsd">
		
		    <!--配置目标类对象-->
		    <bean id="user" class="example1.service.User"></bean>
		
		    <!--配置切面类对象-->
		    <bean id="myAspect" class="example1.MyAspect"></bean>
		
		    <!--配置aop
		        1. 在bean中配置aop约束
		        2. 配置aop:config,把切入点和通知相结合-->
		    <aop:config proxy-target-class="true">
		        <!--切入点
		            expression-表达式
		            要求每个service的方法前后分别开启事务和关闭事务-->
		        <aop:pointcut id="myPointCut" expression="execution(* example1.service.*.*(..))"></aop:pointcut>
		
		        <!--通知 要关联切入点-->
		        <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"></aop:advisor>
		
		    </aop:config>
			</beans>
		
		第五步:
			测试类:
			public class UnitClass {
		
		    @Test
		    public void test() {
		        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		
		        User user = (User) context.getBean("user");
		
		        user.addUser();
		    }
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值