在Spring中,目前我学习了几种增强的方式,和大家分享一下
之前的话:
1.AOP (Aspect Oriented Programming 面向切面编程)
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
面向对象编程是从【静态角度】考虑程序的结构,而面向切面编程是从【动态角度】考虑程序运行过程。
AOP底层,就是采用【动态代理】模式实现的。采用了两种代理:JDK动态代理和CGLIB动态代理。
基本术语(一些名词):
(1)切面(Aspect)
切面泛指【交叉业务逻辑】。事务处理和日志处理可以理解为切面。常用的切面有通知(Advice)与顾问(Advisor)。实际就是对主业务逻辑的一种增强。
(2)织入(Weaving)
织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入。
(3) 连接点(JoinPoint)
连接点是指可以被切面织入的方法。通常业务接口的方法均为连接点
(4)切入点(PointCut)
切入点指切面具体织入的方法
注意:被标记为final的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。
(5)目标对象(Target)
目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。
(6)通知(Advice)
通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间。
(7)顾问(Advisor)
顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。
AOP是一种思想,而非实现
AOP是基于OOP,而又远远高于OOP,主要是将主要核心业务和交叉业务分离,交叉业务就是切面。例如,记录日志和开启事务。
一:前置增强和后置增强
源码介绍:
1.User.java
package cn.zhang.entity;
public class User {
private Integer id; // 用户ID
private String username; // 用户名
private String password; // 密码
private String email; // 电子邮件
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
View Code
2.IDao.java
package cn.zhang.dao;
//定义接口
import cn.zhang.entity.User;
public interface IDao {
//定义方法
public void save(User user);
}
View Code
3.UserDao.java
package cn.zhang.dao.impl;
//实现接口
import cn.zhang.dao.IDao;
import cn.zhang.entity.User;
public class UserDao implements IDao {
@Override
//实现方法
public void save(User user) {
System.out.println("save success!");
}
}
View Code
4.IUserBiz.java
package cn.zhang.biz;
//业务接口
import cn.zhang.entity.User;
public interface IUserBiz {
//待处理的方法
public void save(User user);
}
View Code
5.UserBiz.java
package cn.zhang.biz.impl;
//业务接口的实现类
import cn.zhang.biz.IUserBiz;
import cn.zhang.dao.IDao;
import cn.zhang.entity.User;
public class UserBiz implements IUserBiz {
//引入IDao接口
private IDao dao;
@Override
//实现方法
public void save(User user) {
dao.save(user);
}
//dao 属性的setter访问器,会被Spring调用,实现设值注入
public IDao getDao() {
return dao;
}
public void setDao(IDao dao) {
this.dao = dao;
}
}
View Code
6.LoggerAfter.java(后置增强)
package cn.zhang.aop;
//后置增强
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class LoggerAfter implements AfterReturningAdvice {
@Override
public void afterReturning(Object arg0, Method arg1, Object【】 arg2,
Object arg3) throws Throwable {
System.out.println("后置增强代码");
}
}
View Code
7.LoggerBefore.java(前置增强)
package //代码效果参考:http://www.jhylw.com.cn/014528317.html
cn.zhang.aop;//前置增强
import java.lang.reflect.Method;
import org.apache.log4j.Logger;
import org.springframework.aop.MethodBeforeAdvice;
public class LoggerBefore implements MethodBeforeAdvice {
private static final Logger log = Logger.getLogger(LoggerBefore.class);
@Override
public void before(Method arg0, Object【】 arg1, Object arg2)
throws Throwable {
log.info("前置内容AAA");
System.out.println("前置增强代码");
}
}
View Code
8.applicationContext.xml(Spring配置文件)
<?xml version="1.0" encoding="UTF-8"?>
[/span>beans xmlns=""
xmlns:xsi="" xmlns:aop=""
xmlns:p=""
xsi:schemaLocation="
"
[/span>bean id="dao" class="cn.zhang.dao.impl.UserDao" />
[/span>bean id="biz" class="cn.zhang.biz.impl.UserBiz"
[/span>property name="dao" ref="dao"
[/span>bean id="loggerBefore" class="cn.zhang.aop.LoggerBefore" />
[/span>bean id="loggerAfter" class="cn.zhang.aop.LoggerAfter" />
[/span>aop:config
[/span>aop:pointcut id="pointcut"
expression="execution(public void save(cn.zhang.entity.User))" />
[/span>aop:advisor pointcut-ref="pointcut" advice-ref="loggerBefore" />
[/span>aop:advisor pointcut-ref="pointcut" advice-ref="loggerAfter" />
View Code
当然,针对AOP的配置也可以使用代理对象 ProxyFactoryBean 代理工厂bean来实现,在测试类中:IUserBiz biz=(IUserBiz)ctx.getBean("serviceProxy");
View Code
9.MyTest.java
package cn.zhang.test;
//测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.zhang.biz.IUserBiz;
import cn.zhang.entity.User;
public class MyTest {
public static void main(String【】 args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserBiz biz=(IUserBiz)ctx.getBean("biz");
User user=new User();
biz.save(user);
System.out.println("success!");
}
}
View Code
10.log4j.properties(日志的配置文件)
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
View Code
当然,别忘了引入我们需要的jar包啊!
常用的jar:
二:异常抛出增强和环绕增强
源码介绍:
1.User.java
package cn.zhang.entity;
public class User {
private Integer id; // 用户ID
private String username; // 用户名
private String password; // 密码
private String email; // 电子邮件
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(Integer id, String username, String password, String email) {
super();
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public