一、Java集合框架
1、集合框架
image.png
-
各种集合框架的关系如上图所示,List有序可重复,Set无序不重复,ArrayList的父类是AbstractList,关于三种集合添加元素返回值:
- List调用add()永远返回的是true
- Set调用add()如果是第一次添加返回的是true,否则返回false
- map的键值都可以为null,调用put方法如果是覆盖的话返回上一个值,如果是新添加的话返回null。所以返回null有两种情况,一种是之前没有这个key,另外一种是这个key对应的value是null。
-
Java 集合类:list、set、queue、map、stack 的特点与用法?
- Map
- Map 是键值对,键 Key 是唯一不能重复的,一个键对应一个值,值可以重复。
- TreeMap 可以保证顺序,HashMap 不保证顺序,即为无序的,
- Map 中可以将 Key 和 Value 单独抽取出来,其中 KeySet()方法可以将所有的 keys 抽取成一个 Set,而 Values()方法可以将 map 中所有的 values 抽取成一个集合。
- Set
- 不包含重复元素的集合,set 中最多包含一个 null 元素,只能用 Iterator 实现单项遍历, Set 中没有同步方法。
- List
- 有序的可重复集合,可以在任意位置增加删除元素,用 Iterator 实现单向遍历,也可用ListIterator 实现双向遍历。
- Queue
- Queue 遵从先进先出原则,使用时尽量避免 add()和 remove()方法,而是使用 offer()来添加元素,使用 poll()来移除元素,它的优点是可以通过返回值来判断是否成功,LinkedList实现了 Queue 接口,Queue 通常不允许插入 null 元素。
- Stack
- Stack 遵从后进先出原则,Stack 继承自 Vector,它通过五个操作对类 Vector 进行扩展允许将向量视为堆栈,它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek()方法、测试堆栈是否为空的 empty 方法等。
- 用法
- 如果涉及堆栈,队列等操作,建议使用 List。
- 对于快速插入和删除元素的,建议使用 LinkedList。如果需要快速随机访问元素的,建议使用ArrayList。
- Map
接口里面的变量必须是公开、静态的常量(public static final)
权限修饰符、static、final这三个修饰符的位置可以任意交换
二、“集合”注入
- Spring对于数组、List、Set、Map与Properties五种数据类型的注入需要特别说明。
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<property name="arrays">
<array>
<value>java</value>
<value>html5</value>
</array>
</property>
<property name="list">
<list>
<value>aaa</value>
<ref bean="obj"/>
</list>
</property>
<property name="set">
<set>
<value>aaa</value>
<value>bbb</value>
</set>
</property>
<property name="map">
<map>
<entry key="a" value="aab"/>
<entry key="b" value="bbb"/>
</map>
</property>
<property name="properties">
<props>
<prop key="username">cc</prop>
<prop key="password">dd</prop>
</props>
</property>
</beans>
- 使用property标签对对象成员进行赋值是调用setter方法
- constructor-arg标签的赋值方式是使用构造方法
- 八个基本数据类型加上String都是使用value进行赋值的,其他类型的引用数据类型都是使用ref方式进行赋值
三、Spring AOP
1、第四种方式:config方式
- 基于xml文件,和第三种方式类似,但可以根据方法返回值、包、类、方法与方法参数进行匹配,让符合条件的类或者方法进行动态代理
- 可以指定代理方式:采用Java原生的动态代理还是cglib的动态代理。
Caused by: java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
<!--在pom.xml添加依赖-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>com.springsource.org.aspectj.weaver</artifactId>
<version>1.6.8.RELEASE</version>
</dependency>
IUserService.java
public interface IUserService {
/**
* 获取所有的用户对象列表
* @return
*/
List<Object> getAllUser();
/**
* 保存用户
* @param user
* @return
*/
boolean saveUser(Object user);
/**
* 根据用户uid删除该uid对应的用户信息
* @param uid
* @return
*/
boolean deleteUser(int uid);
/**
* 更新指定用户信息
* @param obj
* @return
*/
boolean updateUser(Object obj);
}
UserServiceImpl.java
public class UserServiceImpl implements IUserService {
@Override
public List<Object> getAllUser() {
System.out.println("--------getAllUser----------");
return new ArrayList<>();
}
@Override
public boolean saveUser(Object user) {
System.out.println("--------saveUser----------");
return true;
}
@Override
public boolean deleteUser(int uid) {
System.out.println("--------deleteUser----------");
return false;
}
@Override
public boolean updateUser(Object obj) {
System.out.println("--------updateUser----------");
return true;
}
}
MyAspect.java
public class MyAspect implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("-----------before----------");
Object obj = invocation.proceed();
System.out.println("-----------after----------");
return obj;
}
}
TestAOP4.java
public class TestAOP4 {
@Test
public void test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("com/aop4/beans.xml");
IUserService us = ac.getBean("us", IUserService.class);
us.getAllUser();
us.deleteUser(1);
us.updateUser(new Object());
us.saveUser(new Object());
}
}
beans.xml
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="us" class="com.aop4.UserServiceImpl"/>
<bean id="ma" class="com.aop4.MyAspect" />
<aop:config proxy-target-class="true">
<!--
定义一个aop的切点
该包com.aop4下所有的任意类,类下的任意含参不含参数的方法,返回值必须为List的方法将会被代理
<aop:pointcut id="pt" expression="execution(java.util.List com.aop4.*.*(..))" />
该包com.aop4下所有的任意类,类下的任意含参不含参数的方法,返回值必须为boolean的方法将会被代理
<aop:pointcut id="pt" expression="execution(boolean com.aop4.*.*(..))" />
com.aop4.UserServiceImpl.deleteUser(int)具体的方法了,参数为int,返回值任意
<aop:pointcut id="pt" expression="execution(* com.aop4.UserServiceImpl.deleteUser(int))" />
多个条件
<aop:pointcut id="pt" expression="(execution(boolean com.aop4.*.*(..)) or (execution(java.util.List com.aop4.*.*(..))))" />
-->
<aop:pointcut id="pt" expression="(execution(boolean com.aop4.*.*(..)) or (execution(java.util.List com.aop4.*.*(..))))" />
<!-- 通知,将MyAspect与切点关联起来 -->
<aop:advisor advice-ref="ma" pointcut-ref="pt" />
</aop:config>
</beans>
- proxy-target-class设置为true,强制使用cglib方式来实现动态代理
2、第五种方式
- 使用-xml通知,代理类不需要实现接口。
IUserService.java
public interface IUserService {
/**
* 获取所有的用户对象列表
* @return
*/
List<Object> getAllUser();
/**
* 保存用户
* @param user
* @return
*/
boolean saveUser(Object user);
/**
* 根据用户uid删除该uid对应的用户信息
* @param uid
* @return
*/
boolean deleteUser(int uid);
/**
* 更新指定用户信息
* @param obj
* @return
*/
boolean updateUser(Object obj);
void getUserByUid();
}
UserServiceImpl.java
public class UserServiceImpl implements IUserService {
@Override
public List<Object> getAllUser() {
System.out.println("--------getAllUser----------");
return new ArrayList<>();
}
@Override
public boolean saveUser(Object user) {
System.out.println("--------saveUser----------");
return true;
}
@Override
public boolean deleteUser(int uid) {
System.out.println("--------deleteUser----------");
return false;
}
@Override
public boolean updateUser(Object obj) {
System.out.println("--------updateUser----------");
return true;
}
@Override
public void getUserByUid() {
System.out.println("--------getUserByUid----------");
System.out.println(1 / 0);
String str = null;
System.out.println(str.length());
}
}
- 五种通知方式来实现aop
- 前置通知,在业务方法之前执行
- 后置通知,在业务方法之后执行
- 环绕通知,同时在业务方法的前后执行
- 带有返回值通知,可以拿到业务方法的返回值
- 异常通知,可以捕获业务方法中的异常对象
- 注意:如果同时配置来所有的通知方式,则执行顺序依次为:
- before>around before>业务方法 >after returning > around after > after
- before>around before>业务方法 >after throwing > after
- ps. 使用注解的话是环绕通知proceed方法之前部分先执行,使用xml配置的话取决于aop:before和aop:around的配置顺序
MyAspect.java
public class MyAspect {
public void myBefore(JoinPoint jp){
// System.out.println("args " + Arrays.toString(jp.getArgs()));
// System.out.println("toString " + jp.toString());
// System.out.println("getTarget " + jp.getTarget());
System.out.println("this is before.");
}
public void myAfter(JoinPoint jp){
System.out.println("this is after.");
}
public Object myAround(ProceedingJoinPoint pjp){
try {
System.out.println("this is around before");
Object obj = pjp.proceed();
System.out.println("this is around after " + obj);
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
/**
* 带有返回值的通知
* @param jp
* @param obj 配置文件中的obj
*/
public void myReturn(JoinPoint jp, Object obj){
System.out.println("this is after returning " + obj);
}
public void myThrow(JoinPoint jp, Throwable e){
System.out.println("this is after throwing " + e.getMessage());
}
}
TestAOP5.java
public class TestAOP5 {
@Test
public void test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("com/aop5/beans.xml");
IUserService us = ac.getBean("us", IUserService.class);
us.updateUser(new Object());
us.getAllUser();
us.saveUser(new Object());
us.deleteUser(1);
us.getUserByUid();
}
}
beans.xml
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="us" class="com.aop5.UserServiceImpl"/>
<bean id="ma" class="com.aop5.MyAspect" />
<aop:config proxy-target-class="true">
<aop:aspect ref="ma">
<aop:pointcut id="mpc" expression="execution(* com.aop5.*.*(..))" />
<aop:around method="myAround" pointcut-ref="mpc" />
<aop:before method="myBefore" pointcut-ref="mpc"/>
<aop:after method="myAfter" pointcut-ref="mpc" />
<aop:after-returning method="myReturn" pointcut-ref="mpc" returning="obj" />
<aop:after-throwing method="myThrow" pointcut-ref="mpc" throwing="e" />
</aop:aspect>
</aop:config>
</beans>
- pointcut切点:程序中需要注入advice的位置的集合,指名执行advice的触发条件
- advice:可以理解为代理方法的实现,向切点注入的代码
- advisor:pointcut和advice的配置器,将advice注入到pointcut的位置
良心zuo教育的千锋 个人学习总结