AOP(面向切面编程)用来做安全验证,记录日志,性能检验等等。
代理模式:对进行操作的对象的对象的代理。
代理对象和被代理对象:
代理分为静态代理和动态代理,静态代理是指在编译阶段就能确定代理对象的被代理对象,代理类需要和被代理类一一对应。
动态代理指在运行阶段确定代理对象的被代理对象(一个代理类可以确定多个被代理类)。
静态代理的实现:
1、定义代理类,代理类应该和被代理类实现同一个接口并封装被代理对象
2、通过代理对象去代替被代理对象完成业务
动态代理:在运行阶段动态的确定代理对象和被代理对象的协议,代理类只有一个,动态代理是基于反射的基础之上实现的。反射是指通过获得类的Class实例,可以得到该类的内部信息包括实例化。
正常创建学生对象是通过Student s = new Student();
s.setAge(10);
反射是这样的:Class c = Student.class;//每个类里面都有一个静态的常量。class.
c.getClassLoader();//获得加载类器
Student s1 = (Student)c.newInstance();//创建新的实例。这个newInstance调用的是无参构造。所以必须有无参构造。
大Class当然也可以通过类名来获得,也可以通过对象来获得,像上面的Class c1 = s.getClass().
Field fs[] = c.getFields();//获得所有的属性名字,反射的类多在java.lang.reflect包里。.Field
for(int i = 0 ;i<fs.length;i++){
System.out.println(fs[i].getName());//只能打印出共有的属性哈。public那种
}
Method ms[] = c.getMethods();//java.lang.reflect.Method
for(int i = 0 ;i<ms.length;i++){
System.out.println(ms[i].getName());//只能打印出共有的属性哈。public那种
}
c.getField(String fieldname);//获得某个字段的值。
Class c = Student.class;
Student obj = (Student)c.newInstance();
c.getMethod("setAge",int.class).invoke(obj,new Integer[]{2});//通过Class的实例的方法getMethod();第一个参数传方法名:setAge,字符串型的呀。第二个参数传参数类型的class.因为setAget(int aget);方法invoke的第一个参数obj是要调用哪个对象实例的方法 ,这个是对象的实例。第二个参数是调用setAge时参数的值。这里是2.
System.out.println(obj.getAge());//显示为2
学反射是为了学习动态代理。
动态代理第一步:定义代理类,代理类实现InvocationHandler,实现invoke方法,并封装被代理对象,创建带参数构造把被代理对象传进去啊。被代理对象为Object类型。
StudentDaoImp dao = new StudentDaoImp();
StudentDaoService daoService = new StudentDaoServiceImp(dao);
//动态代理是基于接口的代理
DynamicProxy dp = new DynamicProxy(daoSerivice);
//生成代理对象
StudentDaoSerivce service = (StudentDaoService)Proxy.newProxyInstance(StudentDaoServiceImp.class.getClassLoader(),//被代理对象的类的加载器
StudentDaoServiceImp.class.getInstances(),//被代理类所实现的全部接口
dp);
service.delete(new Student());
AOP:Aspact Object Programming面向切面编程。切面是指用来处理安全验证,性能测试,和记录日志的类。我们叫做切面。切面也是一个类。一个抽象化的叫法。属于切面的类中有方法可以横切业务逻辑类的方法。
AOP代理有JDK动态代理或者CGLIB代理。前者是对接口的代理,后者是对类的代理。
在ApplicationContext.xml中进行AOP的配置
<bean name="myAspect" class="com.ts.aspect.MyAspect"></bean>
<aop:config>
<aop:pointcut expression="excution(* com.ts.service.imp.Student.*(..))" id="pcMethod"/>///星的位置表示关注点要横切的方法的返回值类型。*表任意类型。*后面是空格,再后面是要横切的类的包或者类。类的*表示这个类的所有方法都要横切。括号里的点点表示任意个参数,如果括号里是空的,表示调用无参构造,也可以指定参数的类型。注意啊。id是不能重的。给id起一个名标识唯一。
上面是连接点。下面是通知。
<aop:aspect id="aspect" ref="myAspect">///把上面定义的切面引入进来
<aop:after method="doAfter" pointcut-ref="pcMethod"/>
<aop:before method="doBefore" pointcut-ref="pcMethod"/>///pointcut-reft指定上面定义的pointcut的id.
</aop:aspect>
</aop:config>
spring有一个JoinPoint。把这个当做参数传到切面的方法中,可以通过jp.getSignature().getName()得到切面方法的名字。可以通过jp.getArgs()得到切面方法的参数数组。
如果是doAround.中间还可以传一个ProceedingJoinPoint类型的参数。
切面类型中有如下切面方法 。
public void doAround(ProceedingJointPoint pjp){
long time1 = System.currentTimeMillis();
pjp.proceed();
long time2 = System.currentTimeMillis();
System.out.println("执行"+pjp.getSignature().getName()+"()方法共耗时"+(time2-time1)+"毫秒");
Spring是一个强大的框架,它对Struts提供也支持,也对Hibernate提供了支持。只需要提供相关的jar包就行了。
在Spring中进行事务管理器的配置。
下面定义了一个Spring的sessionFactory的Bean。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="file:src/hibernate.cfg.xml">
</property>
</bean>
<!--配置事务管理器对象-->
<bean name="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!--注入sessionFactory对象 -->
<property name="sessionFactory" ref="sessionFactory">
</bean>
<!-- 配置纳入事务管理中的方法--!>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--需要开启事务管理的时候自动开启---!>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!--需要事务连接点---!>
<aop:pointcut expression="execution(* com.ts.service.imp.*.*(..))" id="pcMethod"/>
<!--需要通知---!>
<aop:advice advice-ref="txAdvice" pointcut-ref="pcMethod"/>
</aop:config>