昆明java培训
达内昆明广州春城路

18487146383

热门课程

【昆明Java培训班】什么是AOP?

  • 时间:2016-10-21
  • 发布:昆明Java培训
  • 来源:达内新闻

昆明Java培训班的老师今天给大家讲什么是AOP。

面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面

1.面向切面编程提供声明式事务管理

2.spring支持用户自定义的切面

面向切面编程(aop)是对面向对象编程(oop)的补充,

面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。

AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,

是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。

aop框架具有的两个特征:

1.各个步骤之间的良好隔离性

2.源代码无关性

话不多说,我们直接来代码,加强理解

昆明Java培训班的老师先给大家看一个简单的例子:Spring AOP实现日志的输出,即后置增强和前置增强

我们看看代码

aop包下

我们要实现AfterReturningAdvice接口

public class LoggerAfter implements AfterReturningAdvice {

//save()之后执行它

public void afterReturning(Object returnValue, Method method, Object[] arguments   ,

Object target) throws Throwable {

System.out.println("===========后置增强代码==========");

}

}

前置,我们要实现MethodBeforeAdvice接口

*/

public class LoggerBefore implements MethodBeforeAdvice {

//获取日志对象

private static final Logger log = Logger.getLogger(LoggerBefore.class);

//save()之前执行它

public void before(Method method, Object[] arguments, Object target)

throws Throwable {

log.info("==========前置增强代码==========");

}

}

实现类:

biz:

public class UserBiz implements IUserBiz {

//实例化所依赖的UserDao对象,植入接口对象

private IDao dao;

public void save2(User user) {       

//调用UserDao的方法保存信息

dao.save(user);

}

//dao属性的setter访问器,会被Spring调用,实现设值注入

public IDao getDao() {

return dao;

}

public void setDao(IDao dao) {

this.dao = dao;

}

dao:

public class UserDao implements IDao {

/**

*保存用户信息的方法

* @param user

*/

public void save(User user) {

System.out.println("save success!");

}

}

src下的applicationContext.xml

<!--配置实现类 -->

<bean id="dao" class="cn.wgy.day01.dao.impl.UserDao"/>

<bean id="biz" class="cn.wgy.day01.biz.impl.UserBiz">

<property name="dao" ref="dao"></property>

</bean>

<!--定义前置增强组件-->

<bean id="loggerBefore" class="cn.wgy.day01.aop.LoggerBefore"/>

<!--定义后置增强组件-->

<bean id="loggerAfter" class="cn.wgy.day01.aop.LoggerAfter"/>

<!--代理对象ProxyFactoryBean代理工厂bean-->

<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="targetName" value="biz"></property>

<property ame="interceptorNames" value="loggerBefore,loggerAfter"></property>

</bean>

<!--针对AOP的配置

<aop:config>

execution:调用那个方法

<aop:pointcut id="pointcut" expression="execution(public void save2(cn.wgy.day01.entity.User))"/>

将增强处理和切入点结合在一起,在切入点处插入增强处理,完成"织入"

<aop:advisor pointcut-ref="pointcut" advice-ref="loggerBefore"/>

<aop:advisor pointcut-ref="pointcut" advice-ref="loggerAfter"/>

</aop:config> -->

test

public static void main(String[] args) {

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

//获取到biz对象,即业务逻辑层对象

IUserBiz biz=(IUserBiz)ctx.getBean("serviceProxy");

User user=new User();

/**

*执行这个方法时,先走前置增强,before(),然后走中间的方法,最后走后置增强

*/

biz.save2(user);

System.out.println("success!");

}

这个简单的例子就很好的体现出了Spring AOP的力量

顺便我们一起来看看其他增强类型

环绕增强:可以把前置增强和后置增强结合起来,spring吧目标的方法的控制权全部交给了它。我们要实现MethodInterceptor接口

aop:

public class AroundLog implements MethodInterceptor {

private static final Logger log = Logger.getLogger(AroundLog.class);

public Object invoke(MethodInvocation arg0) throws Throwable {

/*Object target = arg0.getThis(); //获取被代理对象

Method method = arg0.getMethod(); //获取被代理方法

Object[] args = arg0.getArguments(); //获取方法参数

log.info("调用" + target + "的" + method.getName() + "方法。方法入参:"

+ Arrays.toString(args));

try {   Object result = arg0.proceed(); //调用目标方法,获取目标方法返回值

log.info("调用" + target + "的" + method.getName() + "方法。"

+ "方法返回值:" + result);

return result;

} catch (Throwable e) {

log.error(method.getName() + "方法发生异常:" + e);       throw e;

}*/

//环绕增强

System.out.println("===before=====");

//调用目标对象的方法

Object result = arg0.proceed();

System.out.println("===after=====");

return result;

}

applicationContext.xml:

<bean id="service" class="cn.wgy.day01.service.UserService"/>

<!--环绕增强 -->

<bean id="around" class="cn.wgy.day01.aop.AroundLog"/>

<!--方式一-->

<!-- <aop:config>

切点

<aop:pointcut expression="execution(public void delete())" id="pointcut"/>

异常抛出增强

<aop:advisor advice-ref="around" pointcut-ref="pointcut"/>

</aop:config> -->

<!--方式二 -->

<!--代理对象ProxyFactoryBean代理工厂bean-->

<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="target" ref="service"></property>

<property ame="interceptorNames" value="around"></property>

</bean>

</beans>

异常增强,我们要实现ThrowsAdvice接口

你注意看没有,都没有实现方法,怎么办呢?你别急,其实已经给我们规定了方法名称,而且必须是它才能。就是void AfterThrowing()它提供了一个参数,三个参数的。

aop:

public class ErrorLog implements ThrowsAdvice {

private static final Logger log=Logger.getLogger(ErrorLog.class);

@SuppressWarnings("unused")

private void AfterThrowing(Method method, Object[] args, Object target,

RuntimeException e) {

log.error(method.getName()+"方法发生异常"+e);

}

service

public class UserService {

public void delete() {

int result=5/0;

System.out.println(result);

}

}

applicationContext.xml

<bean id="service" class="cn.wgy.day01.service.UserService"/>

<bean id="error" class="cn.wgy.day01.aop.ErrorLog"/>

<!--方式二 -->

<!--代理对象ProxyFactoryBean代理工厂bean-->

<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="target" ref="service"></property>

<property ame="interceptorNames" value="error"></property>

</bean>

<!-- <aop:config>

<aop:pointcut expression="execution(public void delete())" id="pointcut"/>

异常抛出增强

<aop:advisor advice-ref="error" pointcut-ref="pointcut"/>

</aop:config> -->

到这里昆明Java培训班的老师要思考一下,我们可以applicationContext.xml里面的bean组件修改修改,我们用了顾问(Advisor)要包装通知(Advice),比较灵活,可以只针对某一个方法进行处理。

对于环绕增强:

<bean id="service" class="cn.wgy.day01.service.UserService"/>

<!--环绕增强 -->

<bean id="around" class="cn.wgy.day01.aop.AroundLog"/>

<!--方式一-->

<!-- <aop:config>

切点

<aop:pointcut expression="execution(public void delete())" id="pointcut"/>

异常抛出增强

<aop:advisor advice-ref="around" pointcut-ref="pointcut"/>

</aop:config> -->

<!--顾问(Advisor)要包装通知(Advice),比较灵活,可以只针对某一个方法进行处理 -->

<bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">

<property ame="advice" ref="around"></property>

<property ame="mappedNames" value="delete"></property>

</bean>

<!--方式二 -->

<!--代理对象ProxyFactoryBean代理工厂bean-->

<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="target" ref="service"></property>

<property ame="interceptorNames" value="advisor"></property>

</bean>

</beans>

还有一个知识点,我们可以更方便的写bean组件,正则表达式

<bean id="service" class="cn.wgy.day01.service.UserService"/>

<!--环绕增强 -->

<bean id="around" class="cn.wgy.day01.aop.AroundLog"/>

<!--方式一-->

<!-- <aop:config>

切点

<aop:pointcut expression="execution(public void delete())" id="pointcut"/>

异常抛出增强

<aop:advisor advice-ref="around" pointcut-ref="pointcut"/>

</aop:config> -->

<bean id="regex" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

<property ame="advice" ref="around"></property>

<property ame="pattern" value=".*do.*"></property>

</bean>

<!--方式二 -->

<!--代理对象ProxyFactoryBean代理工厂bean-->

<!-- <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="target" ref="service"></property>

<property ame="interceptorNames" value="regex"></property>

</bean> -->

<!--默认-->

<!-- <bean class="org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor"></bean>-->

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

<property name="beanNames" value="service"></property>

<property name="interceptorNames" value="regex"></property>

</bean>

到这里呢,算是差不多了,但是我们缺少了分析下源代码

昆明Java培训班的老师知道,实现aop,其实源代码里面通过了动态代理来实现

上一篇:Spring设置注入和构造注入的区别
下一篇:java程序员:代理模式的定义

昆明Java培训班《Java分布式数据库的未来》

昆明java培训班:为什么java工程师薪资这么高?

昆明java培训班:你所不知道的java秘密

昆明java培训班;如何认识Java Web技术

选择城市和中心
贵州省

广西省

海南省

扫一扫

了解更多干货