一.Sqring IOC
1.spring IOC 容器表格
1.2初始化Spring上下文容器(IOC)
ApplicationContext ac=new ClassXmlPathApplicationContext("spring.xml");
二.Spring AOP
1.AOP中关键性概念:
连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
2.AOP工具类:
2.1org.springframework.aop.framework.ProxyFactoryBean用来创建一个代理对象,在一般情况下它需要注入以下三个属性:
proxyInterfaces:代理应该实现的接口列表(List)
interceptorNames:需要应用到目标对象上的通知Bean的名字。(List)
target:目标对象 (Object)
3.AOP三种通知:
3.1:前置通知(org.springframework.aop.MethodBeforeAdvice):在连接点之前执行的通知()
3.2:后置通知(org.springframework.aop.AfterReturningAdvice):在连接点正常完成后执行的通知
3.3:环绕通知(org.aopalliance.intercept.MethodInterceptor):包围一个连接点的通知,最大特点是可以修改返回值,由于它在方法前后都加入了自己的逻辑代码,因此功能异常强大。
它通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用,这样目标方法就不会执行)
前置通知案例:在购书系统当中使用AOP方式实现日志系统
先创建一个通用的接口和实现类
/**
* 目标接口
*/
public interface IBookBiz {
// 购书
public boolean buy(String userName, String bookName, Double price);
// 发表书评
public void comment(String userName, String comments);
}
/**
* 目标实现类
*/
public class BookBizImpl implements IBookBiz {
public BookBizImpl() {
super();
}
public boolean buy(String userName, String bookName, Double price) {
// 通过控制台的输出方式模拟购书
if (null == price || price <= 0) {
throw new PriceException("book price exception");
}
System.out.println(userName + " buy " + bookName + ", spend " + price);
return true;
}
public void comment(String userName, String comments) {
// 通过控制台的输出方式模拟发表书评
System.out.println(userName + " say:" + comments);
}
}
/**
* 前置通知,用于目标方法被调用之前进行日志收集
*/
public class BeforeAdvice implements MethodBeforeAdvice {
/**
*
* @param method 目标方法
* @param args 目标方法所执行的参数
* @param target 目标对象
* @throws Throwable
*/
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
//获取被调用的方法名
String methodName = method.getName();
//获取目标方法的类的全路径名
String className = target.getClass().getName();
System.out.println("[前置通知]"+className+"."+methodName+
"执行参数:"+ Arrays.toString(args));
}
}
<!--代理=通知+目标 只有完整的代理对象才具有AOP特性,而AOP代码是写在通知中-->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--通知-->
<property name="interceptorNames">
<list>
<!--前置通知-->
<value>beforeAdvice</value>
<!--...此处加多个通知-->
</list>
</property>
<!--目标-->
<property name="target">
<ref bean="BookBizTarget"/>
</property>
<!--定义代理对象实现的接口-->
<property name="proxyInterfaces">
<list>
<value>biz.IBookBiz</value>
</list>
</property>
</bean>
开始初始化spring.xml上下文并执行目标方法
//1.初始化Spring上下文容器(IOC)
ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
IBookBiz proxy = ac.getBean("proxy", IBookBiz.class);
//调用buy和comment方法时,会将前置通知应用到目标方法上得到代理对象
proxy.buy("李四","西游记",200d);
proxy.comment("李四","好看,名著");
IBookBiz bookBiz1=new BookBizImpl();
IBookBiz bookBiz2=new Proxy();
效果:
【前置通知】biz.BookBizImpl.buy执行参数[李四, 西游记, 200.0]
李四 buy 西游记, spend 200.0
【前置通知】biz.BookBizImpl.comment执行参数[李四, 好]
李四 say:好
后置通知案例
/**
* 后置通知
*/
public class AfterAdvice implements AfterReturningAdvice {
/**
*
* @param returnValue 目标方法的返回值
* @param method 目标方法
* @param args 目标方法的执行参数
* @param target 目标对象
* @throws Throwable
*/
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
//获取目标方法名
String methodName = method.getName();
//获取目标方法的类的全路径名
String className = target.getClass().getName();
System.out.println("[后置通知]"+className+"."+methodName+
"执行参数"+ Arrays.toString(args)+"返回值:"+returnValue);
}
}
<!--代理=通知+目标 只有完整的代理对象才具有AOP特性,而AOP代码是写在通知中-->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--通知-->
<property name="interceptorNames">
<list>
<!--前置通知-->
<!--<value>beforeAdvice</value>-->
<!--后置通知-->
<value>afterAdvice</value>
<!--...此处加多个通知-->
</list>
</property>
<!--目标-->
<property name="target">
<ref bean="BookBizTarget"/>
</property>
<!--定义代理对象实现的接口-->
<property name="proxyInterfaces">
<list>
<value>biz.IBookBiz</value>
</list>
</property>
</bean>
//1.初始化Spring上下文容器(IOC)
ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
IBookBiz proxy = ac.getBean("proxy", IBookBiz.class);
//调用buy和comment方法时,会将前置通知应用到目标方法上得到代理对象
proxy.buy("李四","西游记",200d);
proxy.comment("李四","好看,名著");
李四 buy 西游记, spend 200d
【后置通知】biz.BookBizImpl.buy执行参数[李四, 西游记, 200.0]返回值true
李四 say:好看