Feb 1997

Overtime and overdue


  • Home

  • Tags

  • Categories

  • Archives

  • Search

Spring Note 2: Autowire

Posted on 2020-01-04 Edited on 2020-03-30

The Spring container can autowire relationships between collaborating beans.

Example

Dog.java:

1
2
3
4
5
public class Dog {
public void shout() {
System.out.println("wang");
}
}

Cat.java:

1
2
3
4
5
public class Cat {
public void shout() {
System.out.println("miao");
}
}

People.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class People {
private Cat cat;
private Dog dog;
private String name;

@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
public Cat getCat() {return cat;}

public void setCat(Cat cat) {this.cat = cat;}

public Dog getDog() {return dog;}

public void setDog(Dog dog) {this.dog = dog;}

public String getName() {return name;}

public void setName(String name) {this.name = name;}
}

Before autowired

Beans.xml:

1
2
3
4
5
6
7
8
<bean id="cat" class="com.xliu.pojo.Cat"/>
<bean id="dog" class="com.xliu.pojo.Dog"/>

<bean id="people" class="com.xliu.pojo.People">
<property name="name" value="xliu"/>
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
</bean>

After autowired

Beans.xml:

1
2
3
4
5
6
<bean id="cat" class="com.xliu.pojo.Cat"/>
<bean id="dog" class="com.xliu.pojo.Dog"/>

<bean id="people" class="com.xliu.pojo.People" autowire="byName">
<property name="name" value="xliu"/>
</bean>

OR

Beans.xml:

1
2
3
4
5
6
<bean id="cat" class="com.xliu.pojo.Cat"/>
<bean id="dog" class="com.xliu.pojo.Dog"/>

<bean id="people" class="com.xliu.pojo.People" autowire="byType">
<property name="name" value="xliu"/>
</bean>

Noticed that both codes omit the ref="", because using autowire enable spring to automatically search in the context and match the property.

byName & byType

autowire has two value: byName, byType.

  • byName: automatically search in context and match the suffix of setXXX of object with corresponding beanid.

    For example, class people has method setDog() and there is a bean id ="dog", they will match. If we change the id to dog222, then they won’t match and error occurs.

  • byType: automatically search in context and match the class of object with corresponding beanclass. If using byType, we can even skip define bean id because only class is used to match.

    The disadvantage of byType is we can’t register two beans refer to the same class.


Using annotaion

Place @Autowired before the attribute in pojo, for example:

1
2
3
4
@Autowired
private Cat cat;
@Autowired
private Dog dog;

Turn on the support for annotaion in xml:

1
<context:annotation-config/>

With such configuration, many lines can be omitted, we only need:

1
<bean id="people" class="com.xliu.pojo.People"/>

So, this method is based on byType

Spring Note 1: p-namespace & c-namespace

Posted on 2020-01-01 Edited on 2020-03-29

Recap

As we already know, we can define bean properties and constructor arguments as references to other managed beans or as values defined inline.
Spring supports extensible configuration formats with namespaces, which are based on an XML Schema definition.

XML Shortcut with the p-namespace

Before using p-namespace, we register a class in configuration file with <property> label to define the value of parameter. So I personally think p means property here.

How to use

Add a new namespace in as :xmlns:p="http://www.springframework.org/schema/p"
The format of using p-namespace is:

1
2
<bean id="" class=""
p:attr="">

where id and class mean the same as before, p:attr="" means defining the value of a certain parameter

Example

User.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.xliu.pojo;

public class User {
private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

userbeans.xml:

1
<bean id="user" class="com.xliu.pojo.User" p:age="18" p:name="xliu"/>

equals to:

1
2
3
4
<bean id="user" class="com.xliu.pojo.User">
<property name="name" value="xliu"/>
<property name="age" value="18"/>
</bean>

in this example, the value of user and age is defined in userbeans.xml

XML Shortcut with the c-namespace

Before using c-namespace, we register a class in configuration file with <constructor-arg> label to initialize the constructor method. So I personally think c means constructor here.

How to use

Add a new namespace in as :xmlns:c="http://www.springframework.org/schema/c"
The format of using p-namespace is:
<bean id="" class="" c:age="" c:name=""/>
where id and class mean the same as before, c:attr="" means defining the constructor’s parameter

Example

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.xliu.pojo;

public class User {
private String name;
private int age;

public User(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

Different from previous section, I added one constructor with two parameter, age and name, here. Otherwise c-namespace will not be used

userbeans.xml:

1
<bean id="user2" class="com.xliu.pojo.User" c:age="19" c:name="liux"/>

equals to:

1
2
3
4
<bean id="user2" class="com.xliu.pojo.User">
<constructor-arg name="age" value="19"/>
<constructor-arg name="name" value="xliu"/>
</bean>

Same, the constructor is defined.

Conclusion

Both p-namespace and c-namespace can be replaced by either<property>or<constructor-arg>, they are more elegant alternatives.

Spring Note 0: IOC

Posted on 2019-12-30 Edited on 2020-03-29

Spring makes programming Java quicker, easier, and safer for everybody.

以上这句话引用自Spring官网,用于回答问题”Why Spring?”, Spring提高编程效率的一个主要原因就是IOC(Inversion of Control),那么在了解IOC之前需要先了解传统的三层架构。

使用IOC之前

根据我目前的理解,三层架构即为dao层,service层,controller层。在此举个例子介绍。

Dao

接口UserDao:

1
2
3
public interface UserDao {
void getUser(); // 获取用户的方法,待实现
}

实现类UserDaoImpl:

1
2
3
4
5
public class UserDaoImpl implements UserDao {
public void getUser() {
System.out.println("获取用户信息");
}
}

实现类UserDaoMysqlImpl:

1
2
3
4
5
public class UserDaoMysqlImpl implements UserDao{
public void getUser() {
System.out.println("Mysql获取用户信息");
}
}

以此类推可以有很多种实现的方式。

Service

因为目前对service层的理解不够深,所以关于Service层的作用,网上搜集到以下说法:

  1. 粗略的理解就是对一个或多个DAO进行的再次封装,封装成一个服务
  2. dao层用与和底层的数据库打交道,因此只要是不和数据库打交道的都放在service层

接口类UserService:

1
2
3
public interface UserService {
void getUser();
}

实现类UserServiceImpl:

1
2
3
4
5
6
public class UserServiceImpl implements UserService {
UserDao userDao = new UserDaoMysqlImpl();
public void getUser() {
userDao.getUser();
}
}

测试

本来应该是Controller类的,但是这里暂时用测试类。
MyTest:

1
2
3
4
5
6
public class MyTest {
public static void main(String[] args) {
UserServiceImpl userService=new UserServiceImpl();
userService.getUser();
}
}

输出:

1
Mysql获取用户信息

分析

以上方法应该是最初级三层架构的方法:流程大概是用户只需要调用服务层中的类,服务层再去调用底层的dao。

假设现在需要添加需求:Oracle获取用户信息。我需要做以下操作:1. Dao层添加新的实现UserDaoOracleImpl; 2.Service层实现类中创建的实体要改成 new UserOracleImpl()以调用Dao层的Oracle实现;

在此方法中创建对象的控制权在Service层中。


控制反转

Dao层不变,Service层中加入Set方法

Service

实现类ServiceImpl:

1
2
3
4
5
6
7
8
9
10
11
public class UserServiceImpl implements UserService {
UserDao userDao;

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

public void getUser() {
userDao.getUser();
}
}

测试

MyTest:

1
2
3
4
5
6
7
public class MyTest {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoMysqlImpl());
userService.getUser();
}
}

输出:

1
Mysql获取用户信息

分析

三层架构的调用顺序不变,但是在service层中引入set方法,那么将具体使用哪一个dao的实现类的控制权交付到了用户端。在IOC之前,这个控制权相当于写死在Service层中,我们希望尽可能少地更改底层的代码,使用IOC后,我们只需要在MyTest中通过改变setUserDao的参数即可改变实现的方法。


IOC本质

控制反转IOC本质是一种设计思想,依赖注入DI是一种实现的方法,没有IOC的程序中,我们使用面向对象编程,对象的创建与对象之间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。

在Spring中实现控制反转的IOC容器,其实现方式是依赖注入。

LeetCode:20.Valid Parentness

Posted on 2019-12-28

Problem Description

Given a string containing just the characters ‘(‘, ‘)’, ‘{‘, ‘}’, ‘[‘ and ‘]’, determine if the input string is valid.

An input string is valid if:

1. Open brackets must be closed by the same type of brackets.
2. Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

Solution

Based on the property of FILO, stack can help with match the brackets. I only push the left half of bracket and when it comes to a right part of bracket, I use it to match the top of stack, if success, pop the element, if fail, return false.

Code

class Solution {
public boolean isValid(String s) {
Stack stack = new Stack();
char[] stringArr = s.toCharArray();
int len = s.length();
int i = 0;
String temp;
for (i = 0; i < len; i++) {
try {
if (stringArr[i] == ‘(‘ || stringArr[i] == ‘[‘ || stringArr[i] == ‘{‘) {
stack.push(stringArr[i]);
} else if (‘(‘ == stack.peek() && stringArr[i] == ‘)’ || ‘[‘ == stack.peek() && stringArr[i] == ‘]’ || ‘{‘ == stack.peek() && stringArr[i] == ‘}’) {
stack.pop();
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
return stack.empty();

}

}

Better Solution

When it comes to the left half of bracket, push its right part into a stack.
When it comes to the right half of bracket, match it with the top of stack(pop it if match).
At last check the emptiness of stack

Code

public boolean isValid(String s) {
Stack stack = new Stack();
for (char c : s.toCharArray()) {
if (c == ‘(‘)
stack.push(‘)’);
else if (c == ‘{‘)
stack.push(‘}’);
else if (c == ‘[‘)
stack.push(‘]’);
else if (stack.isEmpty() || stack.pop() != c)
return false;
}
return stack.isEmpty();
}

State-based Testing

Posted on 2019-11-19 Edited on 2019-11-21

Generate a state machine

  1. Create a txt file and write code
  2. Change the suffix .txt into .sm
  3. Download SMC
  4. Command Line: java -jar Smc.jar -java Seminar.sm, a new java file ‘SeminarContext.java’ created
  5. Command Line: java -jar Smc.jar -graph Seminar.sm, a new dot file ‘Seminar_sm.dot’ created
  6. Download Graphviz and do configuration
  7. Command Line: dot -Tpng Seminar_sm.dot -o Seminar.png, a new png file ‘Seminar.png’ created

LeetCode:53.Maximum Subarray

Posted on 2019-11-06 Edited on 2019-11-07 In LeetCode

Problem Description

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Wrong Code

1
2
3
4
5
6
7
8
9
10
11
12
13
public int maxSubArray(int[] nums) {
int sum = nums[0];
for (int i=0; i<nums.length;i++){
int temp = nums[i];
for (int j=i+1; j<nums.length; j++){
temp += nums[j];
if(temp>sum){
sum = temp;
}
}
}
return sum;
}

Error Information

Input [-2,1]
Output -1
Expected 1

Wrong Thinking

My program will stop entering the second layer loop when i = nums.length-1 which refer to the last digit. In this situation, when the sum has already been decided and cannot be changed anymore. So I have take this situation into account.

Correct Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public int maxSubArray(int[] nums) {
int sum = nums[0];
for (int i=0; i<nums.length;i++){
int temp = nums[i];
if(temp>sum){
sum = temp;
}
for (int j=i+1; j<nums.length; j++){
temp += nums[j];
if(temp>sum){
sum = temp;
}
}
}
return sum;
}

Review

Just take the situation into account and add another statement in the first layer loop

Better Code

Dynamic Programming

Usually problem about optimization can be solved by dynamic programming. As for DP, the most important thing is finding the recursion within the problem.
In terms of this problem, we define the problem as maxSubArray(int A[],int i). Assume we have the result of problemmaxSubArray(A, i-1), we can get a equation as:
maxSubArray(A,i) = maxSubArray(A,i-1)>0?maxSubArray(A,i-1):0+A[i];
In short, if you know the solution of the maxSubArray which ends up with index i-1, there are two choices: 1. Start a new subarray from index i; 2. Expand the previous subarray with index i.

Code

1
2
3
4
5
6
7
8
9
10
11
12
public int maxSubArray(int[] nums) {
int n = nums.length;
int res = nums[0];
int cmp = res;
for(int i = 1; i < n; i++)
{
int temp = cmp;
res = Math.max(res+nums[i],nums[i]);
cmp = Math.max(res, temp);
}
return cmp;
}

res: biggest value if subarray ends up with nums[i]
cmp: biggest value so far

LeetCode:35.Search Insert Position

Posted on 2019-11-06 In LeetCode

Problem Description

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Analysis

  1. Going through the array
  2. Try to find an index i where nums[i] == target and return the i
  3. If step 2 failed, try to find an index i where nums[i] > target. Notieced that the array is sorted and if we have to insert a digit before nums[i], the index of the digit should be i as well, then we have to break from the loop, otherwise the position will be wrong
  4. There is a possibility that the target is bigger than the biggest one in the array, then the index to insert should be the value of nums.length.

Right Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 public int searchInsert(int[] nums, int target) {
int res = 0;

for (int i = 0; i < nums.length; i++)
{
if(nums[i] == target || nums[i] > target){
res = i;
break;
}else{
res = nums.length;
}
}
return res;
}

LeetCode:27.Remove Element

Posted on 2019-11-06 In LeetCode

Problem Description

Given an array nums and a value val, remove all instances of that value in-place and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

The order of elements can be changed. It doesn’t matter what you leave beyond the new length.

Analysis

Same as the Question 26, change the array and only part of them is required.
Try the same thinking as Question 26.
Use two cursors, 1(int index) is for index and 1(int i) is for going through all the elements.
If only the nums[i] does not equal to the target value, put it at the nums[index]

Right Code

1
2
3
4
5
6
7
8
9
public int removeElement(int[] nums, int val) {
int index = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != val) {
nums[index++] = nums[i];
}
}
return index;
}

LeetCode:26.Remove Duplicates from Sorted Array

Posted on 2019-11-04 Edited on 2019-11-06 In LeetCode

Problem Description

Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Wrong Code

1
2
3
4
5
6
7
8
public int removeDuplicates(int[] nums) {
int c = nums.length;
for(int i = 0; i < nums.length-1; i++){
if (nums[i] == nums[i+1])
c--;
}
return c;
}

Error Information

Your input [1,1,2]
Output [1,1]
Expected [1,2]

Wrong Thinking

I ignored the requirement that requirement of removing the duplicates, and I worte this only to return the length of array without duplicates which means the array wasn’t changed actually.

How Did I Correct the Code

Review

The reason why i was wrong is not doing the modification on array. Besides return the length of array without duplicates, I still have to change the order of digits in the array.

Analysis

Considering the size of an array cannot change, and the clarification in the example said “It doesn’t matter what values are set beyond the returned length”, so what I have to do is move the digit towards if it didn’t show up before and put the repeated digit backward.
Obviously, the first digit is unchanged no matter how does array look like since the array is sorted. We can start from the second one whose index is 1.
We can use two cursors: index and i, and both of index and i starts from the value of 1. Then we set a loop, when we get into the loop, compare the nums[i] with nums[i-1], if they are the same, i move to the next digit while index doesn’t move, otherwise the nums[index] will be updated with the value of nums[i] and both of i and index move to the next digit.
The advantage of this method is we can guarantee that the order before the index is always right and no duplicates.

Right Code

1
2
3
4
5
6
7
8
9
10
11
public int removeDuplicates(int[] nums) {
int index = 1;
for (int i = 1; i < nums.length; i++){
if (nums[i] == nums[i-1]){
continue;
}
nums[index] = nums[i];
index++;
}
return index;
}

Java:集合

Posted on 2019-11-01 Edited on 2019-11-13 In Java

Collection和Map接口

Java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:Collection和Map。
书中提到这样一行代码List<Apple> apples = new ArrayList<Apple>并配上说明:ArrayList向上转型为List。读到这里我很迷惑,难道不是所有的容器都继承自Collection或者Map接口吗,为什么还会有一个List是ArrayList的父类呢?
通过查找资料得到这样两张图表述了Collection和Map两个大接口及其子接口的关系。

1…789…12
Feb 1997

Feb 1997

112 posts
4 categories
24 tags
© 2020 Feb 1997