第一个版本
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 {
//在父类中只有干干净净的业务
public void buy(){
System.out.println("图书购买功能实现........");
}
}
/**
* 子类就是代理类,将父类的图书购买功能添加事务切面
*/
public class SubBookServiceImpl extends BookServiceImpl {
@Override
public void buy() {
try {
//事务切面
System.out.println("事务开启.........");
//主业务实现
super.buy();
//事务切面
System.out.println("事务提交.........");
} catch (Exception e) {
System.out.println("事务回滚.........");
}
}
}
public class MyTest02 {
@Test
public void test02(){
BookServiceImpl service = new SubBookServiceImpl();
service.buy();
}
}
第三个版本
3)第三个版本:使用静态代理拆分业务和切面.业务和业务接口已拆分.此时切面紧耦合在业务中.
public interface Service {
//规定业务功能
void buy();
}
/**
* 目标对象:业务功能的具体实现
*/
public class BookServiceImpl implements Service {
@Override
public void buy() {
System.out.println("图书购买业务功能实现............");
}
}
public class ProductServiceImpl implements Service {
@Override
public void buy() {
System.out.println("商品购买业务实现.........");
}
}
/**
* 静态代理已经实现了目标对象的灵活切换
* 图书购买业务,商品购买业务
*/
public class Agent implements Service {
//设计成员变量的类型为接口,为了灵活切换目标对象
public Service target;
//使用构造方法传入目标对象
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 MyTest03 {
@Test
public void test02(){
Service agent = new Agent(new ProductServiceImpl());
agent.buy();
}
}
第四个版本
4)第四个版本:使用静态代理拆分业务和业务接口,切面和切面接口.
public interface Service {
//规定业务功能
void buy();
}
/**
* 目标对象:业务功能的具体实现
*/
public class BookServiceImpl implements Service {
@Override
public void buy() {
System.out.println("图书购买业务功能实现............");
}
}
public class ProductServiceImpl implements Service {
@Override
public void buy() {
System.out.println("商品购买业务实现.........");
}
}
public interface AOP {
//该方法不用 必须实现,用到实现即可
default void before(){}
default void after(){}
default void exception(){}
}
public class LogAop implements AOP {
@Override
public void before() {
System.out.println("前置日志输出.......");
}
}
public class TransAop implements AOP {
@Override
public void before() {
System.out.println("事务开启........");
}
@Override
public void after() {
System.out.println("事务提交........");
}
@Override
public void exception() {
System.out.println("事务回滚........");
}
}
public class Agent implements Service {
//传入目标(业务)对象,切面对象
Service target;
AOP aop;
//使用构造方法初始化业务对象和切面对象
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 MyTest04 {
@Test
public void test02(){
Service agent = new Agent(new ProductServiceImpl(),new TransAop());
//切入多个切面的功能
Service agent1 = new Agent(agent,new LogAop());
agent1.buy();
}
}
第五个版本
5)第五个版本:使用动态代理完成第四个版本的优化.
public interface Service {
//规定业务功能
void buy();
//增加有参有返回值的方法测试代理功能
default String show(int age){return null;}
}
/**
* 目标对象:业务功能的具体实现
*/
public class BookServiceImpl implements Service {
@Override
public void buy() {
System.out.println("图书购买业务功能实现............");
}
@Override
public String show(int age) {
System.out.println("这是show()方法被调用...."+age);
return "abcd";
}
}
public class ProductServiceImpl implements Service {
@Override
public void buy() {
System.out.println("商品购买业务实现.........");
}
}
public interface AOP {
default void before(){}
default void after(){}
default void exception(){}
}
public class LogAop implements AOP {
@Override
public void before() {
System.out.println("前置日志输出.......");
}
}
public class TransAop implements AOP {
@Override
public void before() {
System.out.println("事务开启........");
}
@Override
public void after() {
System.out.println("事务提交........");
}
@Override
public void exception() {
System.out.println("事务回滚........");
}
}
public class ProxyFactory {
public static Object getAgent(Service target,AOP aop){
//返回生成的动态代理对象
return Proxy.newProxyInstance(
//类加载器
target.getClass().getClassLoader(),
//目标对象实现的所有的接口
target.getClass().getInterfaces(),
//代理功能实现
new InvocationHandler() {
@Override
public Object invoke(
//生成的代理对象
Object proxy,
//正在被调用的目标方法buy(),show()
Method method,
//目标方法的参数
Object[] args) throws Throwable {
Object obj = null;
try {
//切面
aop.before(); //事务 日志
//业务
obj = method.invoke(target,args);
//切面
aop.after();
} catch (Exception e) {
//切面
aop.exception();
}
return obj; //目标方法的返回值
}
}
);
}
}
public class MyTest05 {
@Test
public void test02(){
//得到动态代理对象
Service agent = (Service) ProxyFactory.getAgent(new BookServiceImpl(),new TransAop());
agent.buy();
}
@Test
public void test03(){
//得到动态代理对象
Service agent = (Service) ProxyFactory.getAgent(new BookServiceImpl(),new LogAop());
System.out.println(agent.getClass());
String s = agent.show(22);
System.out.println(s);
}
}
Spring原生AOP代码实现(了解)
重要的是Aspect框架
public interface BookService {
public boolean buy(String userName,String bookName,double price);
public void comment(String userName,String comments);
}
public class BookServiceImpl implements BookService {
@Override
public boolean buy(String userName, String bookName, double price) {
System.out.println("购买图书功能实现...........");
System.out.println(userName+"购买了"+bookName+",花费了"+price+"元.");
System.out.println(userName+"增加了"+(price/10));
System.out.println("图书购买业务结束");
return false;
}
@Override
public void comment(String userName, String comments) {
System.out.println("评论功能的实现 ...........");
System.out.println(userName+"发表了"+comments+".");
System.out.println("评论功能结束 ...........");
}
}
public class LogAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("\n[系统日志]"+sf.format(new Date())+"---"+method.getName()+ Arrays.toString(objects));
}
}
<?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">
<!--创建业务对象-->
<bean id ="bookServiceTarget" class="com.bjpowernode.service.impl.BookServiceImpl"></bean>
<!--创建切面的对象-->
<bean id="logAdvice" class="com.bjpowernode.advice.LogAdvice"></bean>
<!--绑定业务和切面-->
<bean id="bookService" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--配置业务接口-->
<property name="interfaces" value="com.bjpowernode.service.BookService"></property>
<!--配置切面-->
<property name="interceptorNames">
<list>
<value>logAdvice</value>
</list>
</property>
<!--织入-->
<property name="target" ref="bookServiceTarget"></property>
</bean>
</beans>
public class MyTest {
@Test
public void test01(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService proxy = (BookService) ac.getBean("bookService");
System.out.println(proxy.getClass());
proxy.buy("张三","平凡的世界",55);
proxy.comment("张三","还是很好看,可以看一看.....");
}
}