spring AOP

  Spring AOP(面向切面编程):    

    

    那么切面(aspect)是啥?

    一个关注点的模块化,通常是一个类;通常会横切多个对象;

   再来说说为什么要有aop,我们都知道java是面向对象的语言,3大特性,封装、继承、多态。我们使用类来区别不同兑现,类是对一类“事物”的属性与行为的抽象。那么现在我们我们需要做一个日志系统,来记录操作,输出日志信息这个功能并不是其它类的属性或者行为,也就是和其他类并没有太多的关系,因此我们需要写一个日志类,那么问题来了!!既然是日志,系统中肯定有许多地方需要用到,那么在需要用到的地方,我们就需要调用,一旦需要修改的时候,极为不便,那么面向切向编程(AOP)就可以很好的解决这个问题!

    

  理解:Aop就是将动态代理封装了起来,只用写好的真实对象,和额外实现的方法也就是公共业务,在不改变源代码的基础上,插入了功能,实现了公共业务的重复利用,这样也提高了开发效率;


现在来看看spring aop 的一些名词:

关注点:增加的某个业务,例如:日志,安全,事务等;

切面(aspect):一个关注点的模块化,通常是一个类;通常会横切多个对象;

连接点(JoinPoint):某个方法的执行

通知(advice):在切面的某个连接点上执行的特定的动作。包括了aroundbeforeAfter等不同类型的通知;

织入(Weaving):把切面连接其它的应用程序类型或者对象上,并创建一个被通知的对象

使用spring实现aop

支持:java 5.0引入了java.lang.instrument,允许在jvm启动时启用一个代理类,通过该代理类在运行期间修改类的字节码,改变一个类的功能,实现AOP功能;

第一种是实现方式-通过spring APi来实现:

    实现MethodBeforeAdvice接口:

public class Log implements MethodBeforeAdvice{
	/**
	 * @param method 被调用方法对象
	 * @param args 被调用的方法的参数
	 * @param target 被调用的方法的目标对象
	 * */
	@Override
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行");
	}
}

配置文件 使 Log 类和对应的类进行关联;
<?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="userService" class="com.ccc.service.impl.UserServiceImpl"/>
    <bean id="log" class="com.ccc.log.Log"/>
    <aop:config>
    	<aop:pointcut expression="execution(* com.ccc.service.impl.UserServiceImpl.add())" id="pointcut"/>
    	<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

 com.ccc.service.impl.UserServiceImpl.add()

execution中为被切的对象方法,可以想象成把日志功能横切嵌入进去

.add()表示add方法, 表示所有方法可以用.*() ()表示无参数,而有参可以用(..)表示所有个数的参数

运行结果:

com.ccc.service.impl.UserServiceImpl的add方法被执行
增加用户

第二种实现方式:通过自定义类来实现

public class UserService {
	public void add(){
		System.out.println("i  am  add method");
	}
	public void delete(){
		System.out.println("i am  delete method");
	}

public class Log {
	public void beforelog(){
		System.out.println("i am beforelog");
	}
	public void afterlog(){
		System.out.println("i am afterlog");
	}
}

配置文件:

<bean id="service" class="com.czy.service.UserService"/>
    <bean id="log" class="com.czy.log.Log"/>
    <aop:config>
    	<aop:aspect ref="log"><!--引入切面类-->
    		<aop:pointcut expression="execution(* com.czy.service.UserService.*())" id="pointcut"/>
    		<aop:before method="beforelog"  pointcut-ref="pointcut"/>
    	</aop:aspect>
    </aop:config>


可以看出在执行add方法的时候,拦截器拦截,先输出了日志;

第三种方式:通过注解实现aop

说实话,个人感觉前两种配置文件太繁琐了.....第三中方法的配置文件如下(头部dtd约束省略):

<bean id="service" class="com.czy.service.UserService"/>
    <bean id="log" class="com.czy.log.Log"/>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

这样就一条....使用spring的配置自动完成创建代理织入切面的工作。

//表示这是一个切面
@Aspect    
public class Log {
	@Before("execution(* com.czy.service.UserService.*())")
	public void beforelog(){
		System.out.println("i am beforelog");
	}
	public void afterlog(){
		System.out.println("i am afterlog");
	}
}

注解:  @Aspect:表示这是一个切面

            @Before:在方法执行前执行

            @Around:环绕,在前后都执行一次

//表示这是一个切面
@Aspect    
public class Log {
	@Before("execution(* com.czy.service.UserService.*())")
	public void beforelog(){
		System.out.println("i am beforelog");
	}
@After("execution(* com.czy.service.UserService.*())")
	public void afterlog(){
		System.out.println("i am afterlog");
	}

环绕通知与前置后置通过不同,需要带一个参数

@Around("execution(* com.czy.service.UserService.*())")
	public void aroundlog(ProceedingJoinPoint pjp){
		System.out.println("abefore log");
		System.out.println(pjp.getSignature());
		System.out.println("aafter log");

运行结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值