目录
一.概念
AOP(Aspect Orient Programming)。
切面:公共的,通用的,重复的功能称为切面,面向切面编程就是将切面提取出来,单独开发,在需要调用的方法中通过动态代理方式进行织入。
二.手写AOP框架
版本1:
//图书购买业务和事务切面耦合在一起
public class BookServiceImpl {
public void buy(){
try{
System.out.println("事务开启");
System.out.println("图书购买业务功能实现");
System.out.println("事务提交");
}catch(Exception e){
System.out.println("事务回滚");
}
}
}
版本2:
public class BookServiceImpl {
//todo 在父类中只有业务
public void buy(){
System.out.println("图书购买业务功能实现");
}
}
//todo 子类是代理类,将父类的图书购买功能添加事务的切面
public class SubBookServiceImpl extends BookServiceImpl{
@Override
public void buy() {
try{
//todo 事务的切面
System.out.println("事务开启");
//todo 主业务实现
super.buy();
//todo 事务切面
System.out.println("事务提交");
}catch(Exception e){
System.out.println("事务回滚");
}
}
}
将业务和切面分开,实现了相同的功能
版本3:
静态代理,实现业务灵活切换,切面的功能在代理中体现。
public interface Service {
//todo 业务功能
void buy();
}
//todo 业务功能的具体实现
public class BookServiceImpl implements Service{
@Override
public void buy() {
System.out.println("图书购买业务实现");
}
}
public class FoodServiceImpl implements Service{
@Override
public void buy() {
System.out.println("购买食品业务");
}
/*todo 静态代理已经实现了目标对象的灵活切换,如图书购买业务,食品购买业务*/
public class Agent implements Service{
//todo 设计成员变量为接口,为了灵活切换目标对象
public Service target;
//todo 使用构造方法传入目标对象
public Agent(Service target){
this.target = target;
}
@Override
public void buy() {
try{
//切面功能
System.out.println("事务开启");
//业务功能
target.buy();
//切面功能
System.out.println("事务开启");
}catch(Exception e){
System.out.println("事务回滚");
}
}
}
public class Test {
@org.junit.Test
public void test(){
Agent bookAgent = new Agent(new BookServiceImpl());
bookAgent.buy();
Agent foodAgent = new Agent(new FoodServiceImpl());
foodAgent.buy();
}
}
版本4:
在静态代理中,会发现代理实现的切面功能是死的只能实现事务功能,不能灵活调用其他的切面功能比如日志权限验证功能。
有了接口使业务的功能实现更加灵活。
代理要实现切面接口而不是将切面接口的对象传进来。
要是传对象的话,业务接口和切面接口耦合在代理对象中,业务有变化或切面有变化,代理都得改变。
public interface AOP {
//default 实现类没必要实现该接口中所有的方法
default void before(){};
default void after(){};
default void exception(){};
}
public class LogAOP implements AOP{
@Override
public void before() {
System.out.println("日志输出");
}
}
public class TransactionAOP implements AOP{
@Override
public void before() {
System.out.println("事务开启");
}
@Override
public void after() {
System.out.println("事务提交");
}
@Override
public void exception() {
System.out.println("事务回滚");
}
}
/*todo 静态代理已经实现了目标对象的灵活切换,如图书购买业务,食品购买业务*/
public class Agent implements Service,AOP{
//todo 设计成员变量为接口,为了灵活切换目标对象
public Service target;
public AOP aop;
//todo 使用构造方法传入目标对象
public Agent(Service target,AOP aop){
this.target = target;
this.aop = aop;
}
@Override
public void buy() {
try{
//切面功能
aop.before();
//业务功能
target.buy();
//切面功能
aop.after();
}catch(Exception e){
aop.exception();
}
}
}
public class Test {
@org.junit.Test
public void test(){
pro4.Agent bookAgent = new pro4.Agent(new Boo