AOP概述:
AOP,aspect object programming 面向切面编程
功能:让关注点代码与业务代码分离!
关注点:重复代码就叫做关注点.
切面:关注点形成的类,就叫做切面(类)! 面向切面编程,就是指 对很过功能都有的重复性代码抽取,再在运行的时候往业务方法上动态的植入"切面类代码"
切入点:执行目标对象方法,动态植入切面代码. 可以通过切入点表达式,指定拦截那些类的方法,给指定的类在运行的时候植入切面类代码。
手工方式实现AOP编程(这里我们采用动态代理的方式,并且使用注解的方式把对象添加到容器中)
1)接口类IUserDao
<span style="font-family:Courier New;font-size:14px;">public interface IUserDao {
public void save();
}</span>
2)UserDao实现IUserDao--->动态代理的方式 目标对象必须实现接口
<span style="font-family:Courier New;font-size:14px;">import org.springframework.stereotype.Component;
//这是目标对象
@Component //注解方式 把UserDao添加到IOC容器
public class UserDao implements IUserDao{
public void save() {
System.out.println("用户保存了数据!");
}
}</span>
3)AOP类 这是一个切面类
<span style="font-size:14px;"><span style="font-family:Courier New;">package cn.itcast.myaop_proxy;
import org.springframework.stereotype.Component;
@Component
public class Aop {
public void begin(){
System.out.println("开启事务----");
}
public void end(){
System.out.println("提交事务----");
}
}
</span></span>
<span style="font-family:Courier New;font-size:14px;">package cn.itcast.myaop_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
//这里的放入到IOC容器的是userDaoProxyFactory 不是返回的代理对象 如果所使用注解的方式返回的是UserDaoProxyFactory这个对象
public class UserDaoProxyFactory {
public static Object target;
public static Aop aop;
public static Object getInstanceProxy(Object target_,Aop aop_){
target=target_;
aop=aop_;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
aop.begin();
Object objValue=method.invoke(target, args);
aop.end();
return objValue;//这里返回的是代理对象
}
});
}
}</span>
5)bean.xml配置文件
<span style="font-size:14px;"><span style="font-family:Courier New;"><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启扫描机制 -->
<context:component-scan base-package="cn.itcast.myaop_proxy"></context:component-scan>
<!-- 调用工厂方法,返回UserDao代理后的对象 -->
<bean id="userDaoProxyFactory" class="cn.itcast.myaop_proxy.UserDaoProxyFactory" factory-method="getInstanceProxy">
<constructor-arg index="0" ref="userDao"></constructor-arg> <!- 给静态方法添加参数->
<constructor-arg index="1" ref="aop"></constructor-arg> </span></span><span style="font-family: 'Courier New';font-size:14px;"><!- 给静态方法添加参数-></span><pre name="code" class="html" style="font-family: 'Courier New';font-size:14px;">
</bean></beans>
6)测试类App
<span style="font-family:Courier New;font-size:14px;">import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
ApplicationContext ac=new ClassPathXmlApplicationContext("cn/itcast/myaop_proxy/bean.xml");
@Test
public void test(){
IUserDao userDao= (IUserDao) ac.getBean("userDaoProxyFactory");//返回的是代理类对象
System.out.println(userDao.getClass());
userDao.save();
}
}</span>
运行测试:
在本次编写程序遇到的问题:下面的配置是错误的!!!!!!!
对于代理工厂类的编写:我采用了注解的方式...
这里的放入到IOC容器的是userDaoProxyFactory,而不是返回的代理对象.
如果使用注解的方式返回的是UserDaoProxyFactory这个对象,而我们需要的是UserDao这个对象是UserDaoProxyFactory
<span style="font-family:Courier New;font-size:14px;">package cn.itcast.myaop_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
@Component//这里的放入到IOC容器的是userDaoProxyFactory 不是返回的代理对象 如果所使用注解的方式返回的是UserDaoProxyFactory这个对象
public class DaoProxyFactory1 {
@Resource
public Object target;
@Resource
public Aop aop;
public Object getInstanceProxy(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
aop.begin();
Object objValue=method.invoke(target, args);
aop.end();
return objValue;//这里返回的是代理对象
}
});
}
}</span>
bean.xml的配置:直接开启扫描机制即可 因为对象都放入到了容器..这种想法是错误的,我们需要的是代理对象不是工厂类本身