<file_sep># 学习Spring源码的一些实例、心得

## ioc相关

有2个祖宗级接口：`BeanFactory`、`BeanDefinition`

`BeanFactory`有很多的实现类，`DefaultListableBeanFactory`就是其中之一。

`DefaultListableBeanFactory`里面就有一个`Map<String, BeanDefinition> beanDefinitionMap`, 这个Map对应到`beans.xml`文件，它的key是bean的名字，BeanDefiniton就是bean的定义。Spring容器只要根据这个Map，就能够产生各个bean对象了。<file_sep>package com.changer.log4j.aa.b;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-05-12
 */
public class Person {
    public static final Logger logger = LoggerFactory.getLogger(Person.class);

    private String name;
    private int age;

    public Person() {
        logger.info("[jdLogger] Person constructing...");
    }

    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;
    }
}
<file_sep>## 在spring-boot中使用log4j2

需要完成一下操作：

1，`pom`中要排除spring-boot默认的日志框架，新增log4j2的依赖。

``` xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!--增加log4j2的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
```

2，在`resources/`目录下新增`log4j2.xml`文件。主要的配置如下：

<file_sep>package com.changer.util;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * Created by fcjiang on 15/10/31.
 */
@ConfigurationProperties(prefix = "api")
@Component
public class EnviSettings {
    private String server;
    private String hzbank;

    public String getServer() {
        return server;
    }

    public void setServer(String server) {
        this.server = server;
    }

    public String getHzbank() {
        return hzbank;
    }

    public void setHzbank(String hzbank) {
        this.hzbank = hzbank;
    }
}
<file_sep>package com.changer.util.okhttp3;

/**
 * @Project: MyUtils
 * @Author: fcjiang
 * @Date: 2016-06-15
 */
public class OkHttp3Util {
}
<file_sep>## examples from fcjiang

### Srping的事务管理

主要介绍了2种实现方式：1）基于AspectJ的xml配置方式；2）基于```<tx:annotaion-drive >```的注解方式。
<file_sep>//package com.changer.configs;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//import javax.servlet.ServletException;
//import javax.servlet.annotation.WebServlet;
//import javax.servlet.http.HttpServlet;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//
///**
// * @Project: spring-boot-hello
// * @Author: fcjiang
// * @Date: 2016-06-30
// */
//@WebServlet(urlPatterns = {"/*"})
//public class LogServlet extends HttpServlet {
//    private static final Logger logger = LoggerFactory.getLogger(LogServlet.class);
//
//    @Override
//    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        logger.info("进入doGet方法 pathInfo={}", req.getPathInfo());
//        super.doGet(req, resp);
//    }
//
//    @Override
//    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        logger.info("进入doPost方法 pathInfo={}", req.getPathInfo());
//        super.doPost(req, resp);
//    }
//}
<file_sep>package com.changer.pattern.command;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2017-06-08
 */
public class TurnOnCommand implements Command {
    private TVReceiver tvReceiver;

    public TurnOnCommand(TVReceiver tvReceiver) {
        this.tvReceiver = tvReceiver;
    }

    @Override
    public void execute() {
        tvReceiver.turnOn();
    }
}
<file_sep>package com.changer.controller;

import com.changer.model.ApiResp;
import com.changer.service.PersonService;
import com.changer.staticautowiredt.Person;
import com.rabbitmq.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * @Project: SpringbootDevTest
 * @Author: fcjiang
 * @Date: 2016-06-29
 */
@RestController
@RequestMapping("/person")
public class PersonController {
    private static final Logger logger = LoggerFactory.getLogger(PersonController.class);

    @Autowired
    private PersonService personService;

    @RequestMapping("/testScope")
    public ApiResp testScope() {
        System.out.println("person name: " + personService.getName());
        System.out.println("personService=" + personService);
        System.out.println("personService bean hash code is " + personService.hashCode());
        return new ApiResp("0000", "success");
    }

    @RequestMapping("/all")
    public ApiResp<List<Person>> listAll(@RequestParam("normal") boolean normal) {

        Person person1 = new Person();
        person1.setName("1111");
        person1.setAge(11);
        Person person2 = new Person();
        person2.setName("2222");
        person2.setAge(22);
        List<Person> persons = Arrays.asList(person1, person2);

        if (!normal) {
            throw new IllegalArgumentException("参数normal=false");
        }

        return new ApiResp<>("0000", "success", persons);
    }

    @RequestMapping("/consume")
    public void consume() throws IOException, TimeoutException {
        String EXCHANGE_NAME = "hello_exchange";
        String QUEUE_NAME = "hello_queue";

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

//        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
//        String queueName = channel.queueDeclare().getQueue();
        String queueName = QUEUE_NAME;
        logger.info("exchange_name={}; queueName={}", EXCHANGE_NAME, queueName);
        channel.queueBind(queueName, EXCHANGE_NAME, "");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                logger.info("[消费者] 接收数据={}", message);
            }
        };

        channel.basicConsume(queueName, true, consumer);
    }
}
<file_sep>package com.changer.demo4;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * Created by fcjiang on 15/10/25.
 */
public class AccountService {

    private AccountDao accountDao;
    private TransactionTemplate transactionTemplate;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }


    // 方式一:注解式事务
//    @Transactional
//    public void transfer(String out, String in, Double money){
//        accountDao.outMoney(out, money);
//        int i = 10/0;
//        accountDao.inMoney(in, money);
//    }


    // 方式二:编程式事务
    public boolean transfer(final String out, final String in, final Double money){
        return transactionTemplate.execute(new TransactionCallback<Boolean>() {
            @Override
            public Boolean doInTransaction(TransactionStatus transactionStatus) {
                try {
                    accountDao.outMoney(out, money);
                    int i = 10/0;
                    accountDao.inMoney(in, money);
                    return true;
                }
                catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                    e.printStackTrace();
                    return false;
                }
            }
        });
    }
}
<file_sep>package com.changer.daos.service;

import com.changer.daos.entities.User;
import com.changer.daos.entities.UserCriteria;
import com.changer.daos.mappers.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by enniu on 16/1/28.
 */
@Repository
public class UserDao {

    @Autowired
    private UserMapper userMapper;

    public List<User> getByName(String name){
        if(null != name){
            UserCriteria criteria = new UserCriteria();
            criteria.createCriteria()
                    .andNameEqualTo(name);
            return userMapper.selectByCriteria(criteria);
        }
        return new ArrayList<>();
    }

    public List<User> getAll(){
        UserCriteria criteria = new UserCriteria();
        criteria.createCriteria()
                .andIdGreaterThan(0);
        return userMapper.selectByCriteria(criteria);
    }

}
<file_sep>package com.changer.jdktest.blockqueue;

/**
 * Created by fcjiang on 15/11/27.
 */
public class MainTest {
    public static void main(String[] args) {

        final Business business = new Business();

        new Thread(new Runnable(){
            public void run() {
                for(int i=0; i<5; i++){
                    business.sub(i);
                }
            }
        }).start();


        new Thread(new Runnable(){
            public void run() {
                for(int i=0; i<5; i++){
                    business.main(i);
                }
            }
        }).start();

    }
}
<file_sep>package com.changer.aspecj;

/**
 * Created by fcjiang on 16/4/18.
 */
public class HelloWorldTest {

    public void sayHelloWorld(){
        System.out.println("Hello World in sayHelloWorld()");
    }

    public static void main(String[] args) {
        HelloWorldTest helloWorldTest = new HelloWorldTest();
        helloWorldTest.sayHelloWorld();
    }
}
<file_sep>package com.changer.lambda;

/**
 * @Project: Jdk8Test
 * @Author: fcjiang
 * @Date: 2016-08-06
 */
public class RunnableViaLambda {
    public static void main(String[] args) {
        new Runnable() {
            @Override
            public void run() {
                System.out.println("通过匿名内部类实现Runnable");
            }
        };

        int i = 30;
        Runnable r = () -> {
            System.out.println("通过lambda实现Runnable");
//            i = i + 20;     不能修改外部方法的值
            System.out.println("i = " + i);     // i不需要设置final也可以访问.
        };
        r.run();
    }
}
<file_sep><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.changer</groupId>
    <artifactId>modules</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>integration</module>
        <module>common</module>
        <module>datasource</module>
        <module>web</module>
    </modules>

    <parent>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-parent</artifactId>
        <version>Angel.SR3</version>
    </parent>

    <properties>
        <build.Directory.war>../output/</build.Directory.war>
        <build.Directory.task>../output/</build.Directory.task>
        <extracted-resource>extracted-resource</extracted-resource>
    </properties>

    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
            </exclusions>
        </dependency>
    </dependencies>


    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>

            <!--<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.changer.Application</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>-->
        </plugins>
    </build>

    <!--<build>
        <plugins>
            <plugin>
                &lt;!&ndash;
                    将各个模块中的配置文件单独拿出来，打包的时候发到一起，
                    以便于部署修改（主要是考虑 web/web-audit/predata/task 等独立部署的模块）
                &ndash;&gt;
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependency-resource</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/${extracted-resource}</outputDirectory>
                            <includeGroupIds>${project.groupId}</includeGroupIds>
                            <excludeTransitive>false</excludeTransitive>
                            <includes>*.xml,*.properties</includes>
                        </configuration>
                    </execution>
                </executions>
                </plugin>
        </plugins>
    </build>-->
</project><file_sep>package com.changer.configs;

import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;


/**
 * Created by enniu on 16/1/27.
 */
@Configuration
public class DatabaseConfig {

    @Autowired
    private Environment env;

    @Autowired
    private DataSource dataSource;


    @Bean
    public DataSource dataSource(){

        org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();

        dataSource.setDriverClassName(env.getProperty("db.driver"));
        dataSource.setUrl(env.getProperty("db.url"));
        dataSource.setUsername(env.getProperty("db.username"));
        dataSource.setPassword(env.getProperty("<PASSWORD>"));
        return dataSource;
    }

    @Bean
    public SqlSessionFactory getSqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mybatis/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public PlatformTransactionManager getTransactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}
<file_sep>package com.changer.cglibproxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @Project: AopTest
 * @Author: fcjiang
 * @Date: 2017-02-19
 */
public class CGlibProxyFactory implements MethodInterceptor {
    private Object targetObject;

    public Object createProxy(Object targetObject) {
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println(String.format("在intercept方法中... method=%s; object=; targetObject=%s",
                method.getName(),
                o.getClass().getName(),
                targetObject.getClass().getName()));
        return method.invoke(targetObject, objects);
    }
}
<file_sep>name=fcjiang
age=30
className=com.changer.properties.PropertiesReader<file_sep>## 需要添加swagger2和swagger-ui两个依赖包

## 定义一个SwaggerConfig类，并且使能@EnableSwagger2。指定controller的扫描位置。

## 在MainApp里import进SwaggerConfig类。<file_sep>package com.changer.collectionremove;

import com.alibaba.fastjson.JSON;

import java.util.*;

/**
 * Created by fcjiang on 16/2/22.
 */
public class MainApp {
    public static void main(String[] args) {
        /*Person person = new Person();
        System.out.println(JSON.toJSONString(person));

        BigDecimal salary2 = new BigDecimal("2.0000000");
        person.setSalary(salary2);
        System.out.println(JSON.toJSONString(person));*/

        Long aa = new Long("1437039915000");
        Date bb = new Date(aa);




        List<Person> persons = new ArrayList<>();
        Person fcjiang = new Person("fcjiang", 100);
        Person fcjiang2 = new Person("fcjiang", 99);
        Person sszhu = new Person("sszhu", 20);
        persons.add(fcjiang);
        persons.add(fcjiang2);
        persons.add(sszhu);
        System.out.println(JSON.toJSONString(persons));

        Map<String, Person> tempMap = new HashMap<>();
        for (Iterator<Person> iterator = persons.iterator(); iterator.hasNext(); ){
            Person person = iterator.next();
            tempMap.put(person.getName(), person);
        }

        System.out.println(JSON.toJSONString(tempMap));

        tempMap.remove("sszhu");
        tempMap.get("fcjiang").setAge(30);
        System.out.println(JSON.toJSONString(tempMap));

        System.out.println(JSON.toJSONString(persons));
    }
}
<file_sep>package com.changer.kafkatest;

import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;

/**
 * Created by fcjiang on 15/11/27.
 */
public class ConsumerMsgTask implements Runnable {
    private KafkaStream stream;
    private int threadNum;

    public ConsumerMsgTask(KafkaStream stream, int threadNum) {
        this.stream = stream;
        this.threadNum = threadNum;
    }

    @Override
    public void run() {
        ConsumerIterator<byte[], byte[]> it = stream.iterator();
        while(it.hasNext()){
            System.out.println("Thread " + threadNum + ": " + new String(it.next().message()));
            System.out.println("Shutting down Thread: " + threadNum);
        }
    }
}
<file_sep>package com.changer.fileutil;


import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by fcjiang on 16/3/8.
 */
@Service
public class FileLoader {
    public void read() throws IOException {
        getResource();
    }
    public void getResource() throws IOException {
        InputStream is = this.getClass().getResourceAsStream("/resource/test.txt");
        String fileContent = IOUtils.toString(is);
        System.out.println(fileContent);
    }
}
<file_sep>package com.changer.pattern.bridge;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-12-10
 */
public abstract class Image {
    protected IPlatform platform;

    public abstract void parseFile(String fileName);

    public void setPlatform(IPlatform platform) {
        this.platform = platform;
    }
}
<file_sep>package com.changer.okhttp3;

/**
 * @Project: HelloWorld
 * @Author: fcjiang
 * @Date: 2016-08-14
 */
public enum EndpointEnums {
    OrdersByUserId("/orders/%s", "查询客户订单"),
    OrdersByLoanType("/orders/loanType", "查询产品订单");

    private String url;
    private String desc;

    EndpointEnums(String url, String desc) {
        this.url = url;
        this.desc = desc;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}
<file_sep>package com.changer;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-11-04
 */
public class Demo {
    public static void main(String[] args) {
        Long aa = new Long(10);
        System.out.println(aa.toString());
    }
}
<file_sep>## 使用@ConfigurationProperty注解

特别需要注意，在MainApp加入@EnableConfigurationProperties({DataSourceProperty.class, KafkaProperty.class})。

把要用到的每个xxProperty都显示的放到@EnableConfigurationProperties注解中。

更详细的用法可参照[http://wiselyman.iteye.com/blog/2184586](http://wiselyman.iteye.com/blog/2184586)<file_sep>package com.changer.springboot;

import org.springframework.context.ApplicationContext;

/**
 * @Project: HelloWorld
 * @Author: fcjiang
 * @Date: 2016-11-30
 */
public class MyUtil {
    private  static AccountConfig accountConfig = null;

    static {
        System.out.println("===进入MyUtil static代码块===");
        if (accountConfig == null) {
            ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
            accountConfig = applicationContext.getBean(AccountConfig.class);
//            System.out.println("accountConfig内容" + JSON.toJSONString(accountConfig));
        }
    }

    public static void doSome() {
        System.out.println("在静态工具类中获取到了properties文件中的内容");
        System.out.println("username=" + accountConfig.getUsername() + "; password=" + accountConfig.getPassword());
    }

    public static AccountConfig getAccountConfig() {
        return accountConfig;
    }

    public static void setAccountConfig(AccountConfig accountConfig) {
        MyUtil.accountConfig = accountConfig;
    }
}
<file_sep>package com.changer.pattern.command;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2017-06-08
 * http://blog.csdn.net/jason0539/article/details/45110355
 */
public class App {
    public static void main(String[] args) {
        TVReceiver tvReceiver = new TVReceiver();

        Command command = new TurnOnCommand(tvReceiver);
        command.execute();

        command = new ChangeRadioCommand(tvReceiver);
        command.execute();

        command = new TurnOffCommand(tvReceiver);
        command.execute();
    }
}
<file_sep>package com.changer.configs;

import com.changer.model.ApiResp;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * @Project: SpringbootDevTest
 * @Author: fcjiang
 * @Date: 2016-06-29
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = {IllegalArgumentException.class})
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ApiResp handleIllegalArgumentException() {
        System.out.println("===我是输出===");
        ApiResp apiResp = new ApiResp("1000", "参数错误");
        return apiResp;
    }
}
<file_sep><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.changer</groupId>
    <artifactId>spring-boot-hello</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--配置spring-boot需要的依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.5.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--配置log4j2依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <!--配置rabRabbitMQ依赖-->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>3.6.1</version>
        </dependency>

        <!--配置fastJson依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.5</version>
        </dependency>

        <!--配置commons-config依赖-->
        <dependency>
            <groupId>commons-configuration</groupId>
            <artifactId>commons-configuration</artifactId>
            <version>1.10</version>
        </dependency>


    </dependencies>

</project><file_sep>package com.changer.log4j.aa.c;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-05-12
 */
public class PersonSevice {
    public static final Logger paycenterLogger = LoggerFactory.getLogger("paycenterLogger");
    public static final Logger logger = LoggerFactory.getLogger(PersonSevice.class);

    public void listPerson() {
        paycenterLogger.info("[paycenterLogger] come into listPerson method");
        com.changer.log4j.aa.b.Person person = new com.changer.log4j.aa.b.Person();
        person.setName("fcjiang");
        person.setAge(20);
//        logger.info("[jdLogger]" + JSON.toJSONString(person));
    }
}
<file_sep>http://www.mkyong.com/spring/spring-aop-examples-advice<file_sep>package com.changer.kafkatest;

import kafka.producer.Partitioner;

/**
 * Created by fcjiang on 15/11/27.
 */
public class PartitionerDemo implements Partitioner {
    @Override
    public int partition(Object o, int i) {
        return 0;
    }
}
<file_sep>account.username=fcjiang
account.password=<PASSWORD><file_sep>package com.changer.cipher.msgencode;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.text.MessageFormat;

/**
 * Created by fcjiang on 16/3/16.
 */
public class MainApp {
    public static void main(String[] args) throws IOException {
        String plainMsg = "TodayIsSunday";

        BASE64Encoder base64Encoder = new BASE64Encoder();
        String cipherMsg = base64Encoder.encode(plainMsg.getBytes());
        System.out.println(MessageFormat.format("{0} >>>>BASE64±àÂë>>>> {1}", plainMsg, cipherMsg));

        BASE64Decoder base64Decoder = new BASE64Decoder();
        byte[] resultBytes = base64Decoder.decodeBuffer(cipherMsg);
        String plainMsg2 = new String(resultBytes);
        System.out.println(MessageFormat.format("{0} >>>>BASE64½âÂë>>>> {1}", cipherMsg, plainMsg2));
    }
}
<file_sep>package com.changer.jvmtest.visualvm;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Project: JVMTest
 * @Author: fcjiang
 * @Date: 2016-05-19
 */
public class BTraceDemo {
    public static void main(String[] args) throws ParseException, InterruptedException {
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date targe = sdf.parse("2016-05-19 20:30:00");
        while (new Date().before(targe)) {
            Thread.sleep(5000);
            System.out.println("现在时间: " + sdf.format(new Date()));

            double a = Math.random() * 100;
            double b = Math.random() * 100;
            System.out.println("参数 a = " + a);
            System.out.println("参数 b = " + b);
            System.out.println("计算结果:" + add(a, b));
        }
    }

    public static double add(double a, double b) {
        return a + b;
    }
}
<file_sep>package com.changer.configs;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;

import javax.servlet.Filter;

/**
 * @Project: SpringbootDevTest
 * @Author: fcjiang
 * @Date: 2016-06-29
 */
@Configuration
public class FilterConfig {
    @Bean
    public Filter getEncodingFilter() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        return characterEncodingFilter;
    }
}
<file_sep>package com.changer.rabbitmq;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @Project: HelloWorld
 * @Author: fcjiang
 * @Date: 2016-11-26
 */
public class RabbitMqConsumer {
    /**
     * 从配置文件读取
     */
    private static String host = "127.0.0.1";
    private static int port = 5672;
    private static String vhost = "/fdtClearing";
    private static String userName = "fdtClearing";
    private static String password = "<PASSWORD>";
    private static String exchange = "agreement";
    private static String bindingKey = "agreement.success";


    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(host);
        factory.setPort(port);
        factory.setUsername(userName);
        factory.setPassword(<PASSWORD>);
        factory.setVirtualHost(vhost);

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(exchange, "topic", true);
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, exchange, bindingKey);

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");

                // todo 业务逻辑放在这儿

                System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        // 阻塞在这儿监听
        channel.basicConsume(queueName, true, consumer);

        System.out.println("consumer执行完成");
    }
}
<file_sep>package com.changer.cipher.symmetric;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.NoSuchAlgorithmException;

/**
 * Created by fcjiang on 16/3/17.
 */
public class SymmetricUtil {
    public static byte[] initDESKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
        // 初始化秘钥生成器
        keyGenerator.init(56);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] keyBytes = secretKey.getEncoded();
        return keyBytes;
    }

    public static String encryptByDES(byte[] data, byte[] key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key, "DES");
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] resultBytes = cipher.doFinal(data);
        // todo 加密时byte数组转换成HEX串
        return DatatypeConverter.printHexBinary(resultBytes);
    }

    public static String decryptByDES(byte[] data, byte[] key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key, "DES");
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] resultBytes = cipher.doFinal(data);
        // todo 解密时byte数组转成String对象
        return new String(resultBytes);
    }
}
<file_sep>package com.changer.pattern.observer;

import java.util.Observable;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-05-17
 */
public class ObservableTeacher extends Observable {
    public String publishNotice() {
        return "[明天下雪,放假一天]";
    }

    public void watchWeatherReport(String weather) {
        System.out.println("老师开始观看天气预报...");
        System.out.println("预报: " + weather);
        if (weather.equalsIgnoreCase("下雪")) {
            // todo 只有setChanged之后,notifyObservers才会真正触发observer去执行update方法
            setChanged();
            notifyObservers();
        }
    }

}
<file_sep><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.changer</groupId>
    <artifactId>spring-boot-mysql-mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>spring-boot-mysql-mybatis</name>
    <description>Use Mybatis + MySQL in Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.3.RELEASE</version>
        <relativePath />
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>

        <!--Mysql / DataSource-->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--自行添加用于JSON操作-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.7</version>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>com.changer.Application</start-class>
        <java.version>1.7</java.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.4-SNAPSHOT</version>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.30</version>
                    </dependency>
                    <!--<dependency>
                        <groupId>net.sourceforge.jtds</groupId>
                        <artifactId>jtds</artifactId>
                        <version>${sqlserver-jtds-driver.version}</version>
                    </dependency>-->
                </dependencies>
            </plugin>
        </plugins>
    </build>

</project><file_sep>package com.changer.demo4;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

/**
 * Created by fcjiang on 15/10/25.
 */
public class AccountDao extends JdbcDaoSupport {
    public void outMoney(String out, Double money){
        String sql = "update account set money = money - ? where name = ?";
        this.getJdbcTemplate().update(sql, money, out);
    }

    public void inMoney(String in, Double money){
        String sql = "update account set money = money + ? where name = ?";
        this.getJdbcTemplate().update(sql, money, in);
    }
}
<file_sep>## 消息编码
用到的类是 `BASE64Encoder` 和 `BASE64Decoder`，这两个类所在的包有点特殊是`sun.misc`

消息编码是`可逆的`，编码之后产生的byte[]可以直接转换为String。`new String(byte[] bytes)`

## 消息摘要

用到的类是`MessageDigest`

```
// 获取实例
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
```

消息摘要是`不可逆的` ，摘要值的byte[]不可以直接转换为String。需要借助JDK自带的`DatatypeConverter`转换为十六进制的hex值。

消息摘要有3种实现方式，一种为`MD5`，一种为`SHA`(安全HASH)。其中，`SHA`又分为`SHA-1`/`SHA-256`/`SHA-384`/`SHA-512`. 
还有一种是`Hmac`，它结合了MD5和SHA的优点，需要提供秘钥，然后让秘钥去给内容做消息摘要。`Hmac`常用的形式有`HmacMD5`/`HmacSHA1`/`HmacSHA256`/`HmacSHA384`/`HmacSHA512`

**获取文件的MD5值 不等于 获取文件内容的MD5.**

有一个字符串“helloworld”，还有一个文件aa.txt，文件里的内容也为"helloworld". 字符串的MD5值与aa.txt文件的MD5值不一样。

## 对称加密
加密时用的秘钥和解密时的秘钥相同。

### DES

### 3DES

### AES



## 非对称加密
数据加密：加密时用公钥，解密时用私钥。
`KeyPairGenerator`产生密钥对。

### DH算法

### RSA算法





<file_sep>package com.changer.util;

import com.changer.service.PersonService;

/**
 * Created by fcjiang on 15/11/1.
 */
public class MyUtil {

    private static PersonService personService;

    public static String getPersonServiceName() {
        return personService.getName();
    }

    public void setPersonService(PersonService personService) {
        MyUtil.personService = personService;
    }
}
<file_sep>package com.changer.queue;

import java.util.concurrent.BlockingQueue;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-11-20
 */
public class Consumer implements Runnable {
    private BlockingQueue blockingQueue;

    public Consumer(BlockingQueue blockingQueue) {
        this.blockingQueue = blockingQueue;
    }

    @Override
    public void run() {
        while (blockingQueue.remainingCapacity() > 0) {
            try {
                Thread.sleep(2 * 1000L);
                System.out.println(String.format("队列大小%s, 消费队列中的元素%s", blockingQueue.size(), blockingQueue.take()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
<file_sep>需要引入依赖
```
<!-- joda-time依赖 -->
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.4</version>
</dependency>
```<file_sep>package com.changer.config;

import com.changer.controller.PersonController;
import com.google.common.base.Predicate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Created by bob on 15/9/20.
 */
@EnableSwagger2
@ComponentScan(basePackageClasses = PersonController.class) // 告诉springboot去该controller同级目录下扫描其它controller
public class SwaggerConfig extends WebMvcConfigurerAdapter {

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .paths(apiPaths())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("swagger测试Demo")
                .description("swagger测试Demo，API适用说明。")
                .termsOfServiceUrl("http://127.0.0.1:8080/v2/api-docs")
                .contact("<EMAIL>")
                .license("Apache License Version 2.0")
                .licenseUrl("https://github.com/springfox/springfox/blob/master/LICENSE")
                .version("2.0")
                .build();
    }

    private Predicate<String> apiPaths() {
        return new Predicate<String>() {
            @Override
            public boolean apply(String input) {
                return input.contains("api");   // 适配含“api”关键字的接口
            }
        };
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        super.addResourceHandlers(registry);

        if(!registry.hasMappingForPattern("swagger-ui.html")){
            registry.addResourceHandler("swagger-ui.html")
                    .addResourceLocations("classpath:/META-INF/resources/");
        }

        if(!registry.hasMappingForPattern("/webjars/**")) {
            registry.addResourceHandler("/webjars/**")
                    .addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
    }
}<file_sep>package com.changer.controllers;

import com.alibaba.fastjson.JSON;
import com.changer.models.ApiResp;
import com.changer.models.Person;
import com.changer.utils.RabbitmqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

/**
 * @Project: spring-boot-hello
 * @Author: fcjiang
 * @Date: 2016-06-30
 */
@RestController
@RequestMapping("/person")
public class PersonController {
    private static final Logger logger = LoggerFactory.getLogger(PersonController.class);

    @RequestMapping("/all")
    public ApiResp listAll() {
        Person fcjiang = new Person("fcjiang", 30);
        Person sszhu = new Person("sszhu", 18);
        List<Person> persons = Arrays.asList(fcjiang, sszhu);
        System.out.println("获取persons成功");
        ApiResp<List<Person>> apiResp = new ApiResp<>("0000", "成功", persons);
        return apiResp;
    }

    @RequestMapping("/create")
    public void creat(@RequestParam("name") String name, @RequestParam("age") int age) {
        Person person = new Person(name, age);
        String msg = JSON.toJSONString(person);
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        Connection connection = null;
        Channel channel = null;
        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            channel.exchangeDeclare(RabbitmqUtil.getExchange(), "fanout");
            channel.basicPublish(RabbitmqUtil.getExchange(), RabbitmqUtil.getQueue(), null, msg.getBytes("UTF-8"));
            logger.info("生产:{}", msg);
        }
        catch (Exception e) {
            logger.info("往RabbitMQ中生成内容时异常", e);
        }
        finally {
            try {
                if (channel != null)
                    channel.close();
                if (connection != null)
                    connection.close();
            }
            catch (Exception e) {
                logger.info("关闭channel或者connection时发生异常", e);
            }
        }
    }
}
<file_sep>### 判断字符串中所有字符都为数字
<file_sep>package com.changer.lambda;

import com.alibaba.fastjson.JSON;

import java.util.*;

/**
 * @Project: Jdk8Test
 * @Author: fcjiang
 * @Date: 2016-08-07
 */
public class ComparatorLambdaDemo {
    public static void main(String[] args) {
        List<Human> humans = new ArrayList<>();
        Human sszhu = new Human("sszhu", 18);
        Human fcjiang = new Human("fcjiang", 30);
        Human wukong = new Human("wukong", 500);
        humans.add(sszhu);
        humans.add(fcjiang);
        humans.add(wukong);

//        System.out.println("\n 匿名类方式实现");
//        sortByOldWay(humans);

        System.out.println("\n lambda方式实现");
        sortByOldWay(humans);

    }

    public static void sortByOldWay(List<Human> humans) {
        System.out.println("排序前:" + JSON.toJSONString(humans));
        Collections.sort(humans, new Comparator<Human>() {
            @Override
            public int compare(Human o1, Human o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        System.out.println("排序后:" + JSON.toJSONString(humans));
    }

    public static void sortByLambda(List<Human> humans) {
        System.out.println("排序前:" + JSON.toJSONString(humans));
        humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName()));
        System.out.println("排序后:" + JSON.toJSONString(humans));
    }



    static class Human {
        private String name;
        private int age;

        public Human(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;
        }
    }
}
<file_sep># 初次使用srping-boot
在`pom.xml`文件中添加`parent`和`dependency`.
具体如下:
```
<!--配置spring-boot需要的依赖-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.5.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
```

# spring-boot各知识点学习

## 全局异常处理

增加一个类,添加注解`@ControllerAdvice`


## 添加`filter`和`servlet`以及执行顺序

添加自定义的filter,主要有3种方式:

- 方式1:
    1. 编写自定义的filter类,例如LogFilter.(什么注解都不要加)
    2. 将LogFilter在configuration中实例化为bean.
 
- 方式2:
    1. 定义LogFilter(增加注解`@WebFilter`)
    2. 在Application类前面增加注解`@ServletComponentScan`(这种情况下无需`@Configuration`注入bean)

- 方式3:
    1. 定义LogFilter(无任何注解)
    2. 在`@Configuration`中实例化`ServletRegistrationBean`,并且将LogFilter设置到`ServletRegistrationBean`中.
    
## 添加拦截器`Interceptor`
让application类extends`WebMvcConfigurerAdapter`, 
然后重写`addInterceptors()`方法.

如下:
```
registry.addInterceptor(new UserSecurityInterceptor()).addPathPatterns("/user/**");  
```<file_sep>package com.changer.jvmtest.memoryallocate;

/**
 * 启动参数: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
 *
 * 指定Heap最小20M,最大20M.其中10M是Eden区(-Xmn10M),剩下的10M是老年代. Eden区是Survivor区的8倍, 8x+2x=10M,算出Eden区8M空间.
 *
 * Created by fcjiang on 16/4/15.
 */
public class EdenMinorGC {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[2 * _1MB];
        allocation1 = new byte[4 * _1MB];   // 发生一次MinorGC
    }
}
<file_sep>package com.changer.cipher.msgdigest;

import javax.xml.bind.DatatypeConverter;
import java.text.MessageFormat;

/**
 * Created by fcjiang on 16/3/16.
 */
public class MainApp {

    public static void main(String[] args) throws Exception {
        String plainMsg = "TodayIsSunday";
        System.out.println(MessageFormat.format("{0} >>>>消息摘要 MD5值>>>> {1}", plainMsg, DigestUtil.getMD5(plainMsg)));

        String filePath = "/Users/fcjiang/aa.txt";
        System.out.println(MessageFormat.format("{0} >>>>文件消息摘要 MD5值>>>> {1}", filePath, DigestUtil.getMD5OfFile(filePath)));

        System.out.println(MessageFormat.format("{0} >>>>消息摘要 SHA1值>>>> {1}", plainMsg, DigestUtil.getSHA1(plainMsg)));

        System.out.println(MessageFormat.format("{0} >>>>消息摘要 SHA256值>>>> {1}", plainMsg, DigestUtil.getSHA256(plainMsg)));

        System.out.println(MessageFormat.format("{0} >>>>消息摘要 SHA384值>>>> {1}", plainMsg, DigestUtil.getSHA384(plainMsg)));

        System.out.println(MessageFormat.format("{0} >>>>消息摘要 SHA512值>>>> {1}", plainMsg, DigestUtil.getSHA512(plainMsg)));

        byte[] keyBytes = DigestUtil.initHmacKey();
        System.out.println(MessageFormat.format(">>>>产生HmacMD5秘钥>>>> {0}", DatatypeConverter.printHexBinary(keyBytes)));
        System.out.println(MessageFormat.format("{0} >>>>消息摘要 HmacMD5值>>>> {1}", plainMsg, DigestUtil.getHmacMD5(plainMsg.getBytes(), keyBytes)));
    }
}
<file_sep>package com.changer.cipher.asymmetric;

import javax.crypto.Cipher;
import javax.xml.bind.DatatypeConverter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by fcjiang on 16/3/17.
 */
public class AsymmetricUtil {

    public static Map<String, Object> initRSAKey() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);  // 设置秘钥长度 允许范围512-65536 必须是64的倍数
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<>();
        keyMap.put("rsaPublicKey", rsaPublicKey);
        keyMap.put("rsaPrivateKey", rsaPrivateKey);
        return keyMap;
    }


    public static String encryptByRSA(byte[] data, RSAPublicKey rsaPublicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
        byte[] resultBytes = cipher.doFinal(data);
        // todo 加密时byte数组转换成HEX串
        return DatatypeConverter.printHexBinary(resultBytes);
    }

    public static String decryptByRSA(byte[] data, RSAPrivateKey rsaPrivateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
        byte[] resultBytes = cipher.doFinal(data);
        // todo 解密时byte数组转成String对象
        return new String(resultBytes);
    }
}
<file_sep>## BlockingQueue 阻塞队列

1. 往队列里塞数据 ```queue.put(xxx)```  如果队列已经满了，线程会阻塞。
2. 从队列里读取数据 ```queue.take()```  如果队列里没有可取的数据，线程就会阻塞等在这儿。<file_sep>package com.changer.calendar;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-06-22
 */
public class App {

    public static void main(String[] args) throws ParseException {
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        Date fullAt = sdf.parse("2016-01-31 08:00:00");
        Date fullAt = sdf.parse("2016-03-01 08:00:00");

        System.out.println("fullAt = " + sdf.format(fullAt));
        Date dueAt = calcDueAt(fullAt, 1);
        System.out.println("dueAt = " + sdf.format(dueAt));
        Date userDueAt = calcUserDueAt(fullAt, 1);
        System.out.println("userDueAt = " + sdf.format(userDueAt));
    }

    public static Date calcDueAt(Date fullAt, int curDivNum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fullAt);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        int tDay=calendar.get(Calendar.DAY_OF_MONTH);

        // Calendar加月份,如果对日不存在,Calendar就会是该月的最后一天
        calendar.add(Calendar.MONTH, curDivNum);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return calendar.getTime();
    }

    public static Date calcUserDueAt(Date fullAt, int curDivNum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fullAt);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        int tDay=calendar.get(Calendar.DAY_OF_MONTH);

        // Calendar加月份,如果对日不存在,Calendar就会是该月的最后一天
        calendar.add(Calendar.MONTH, curDivNum);
        int nTDay = calendar.get(Calendar.DAY_OF_MONTH);
        if (nTDay == tDay) {    // 对日存在
            calendar.add(Calendar.DAY_OF_MONTH, -2);
        }
        else {  // 对日不存在
            calendar.add(Calendar.DAY_OF_MONTH, -1);
        }
        return calendar.getTime();
    }
}
<file_sep>package com.changer.pattern.command;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2017-06-08
 */
public class TVReceiver {
    public void turnOn() {
        System.out.println("turn on the TV");
    }

    public void turnOff() {
        System.out.println("turn off the TV");
    }

    public void changeRadio(int channelId) {
        System.out.println("change radio to channel " + channelId);
    }
}
<file_sep>package com.changer.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by fcjiang on 15/11/19.
 */
@RestController
@RequestMapping("person")
public class PersonController {
    @RequestMapping("/sayhello")
    public String sayHello(){
        return "Hello world";
    }
}
<file_sep>package com.changer;

import com.changer.properties.DataSourceProperty;
import com.changer.properties.KafkaProperty;
import com.changer.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by fcjiang on 15/10/31.
 */
@RestController
@SpringBootApplication
@EnableConfigurationProperties({DataSourceProperty.class, KafkaProperty.class})
public class Application {

    @Autowired
    private PersonService personService22;

    @RequestMapping("/")
    String hello(){
        System.out.println("person name: " + personService22.getName());
        System.out.println("personService22=" + personService22);
        System.out.println("personService22 bean hash code is " + personService22.hashCode());
        return "hello to spring boot";
    }

    public static void main(String[] args) throws Exception{
        System.out.println("begin.......................");
        SpringApplication.run(Application.class, args);

        //Person.introduce();

    }
}
<file_sep><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.changer</groupId>
    <artifactId>helloworld</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--测试springboot用-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.3.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!--测试springboot用-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--测试okhttp3需要的依赖-->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.2.0</version>
        </dependency>

        <!--测试okio需要的依赖-->
        <dependency>
            <groupId>com.squareup.okio</groupId>
            <artifactId>okio</artifactId>
            <version>1.8.0</version>
        </dependency>

        <!-- joda-time依赖 -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka_2.11 -->
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka_2.11</artifactId>
            <version>0.10.0.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.9</version>
        </dependency>

        <!--以下为slf4j+log4j2依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.6.2</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.7</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>retrofit</artifactId>
            <version>2.0.2</version>
        </dependency>

	    <!-- https://mvnrepository.com/artifact/com.lmax/disruptor -->
	    <dependency>
		    <groupId>com.lmax</groupId>
		    <artifactId>disruptor</artifactId>
		    <version>3.3.6</version>
	    </dependency>

	    <!-- RabbitMQ依赖包 -->
	    <dependency>
		    <groupId>com.rabbitmq</groupId>
		    <artifactId>amqp-client</artifactId>
		    <version>3.6.5</version>
	    </dependency>

	    <!--google guava库依赖-->
	    <dependency>
		    <groupId>com.google.guava</groupId>
		    <artifactId>guava</artifactId>
		    <version>21.0</version>
	    </dependency>

    </dependencies>

    <!--测试springboot用-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>com.changer.springboot.Application</start-class>
        <java.version>1.7</java.version>
    </properties>


	<profiles>
		<profile>
			<id>check-code</id>
			<build>
				<plugins>
					<plugin>
						<groupId>org.codehaus.mojo</groupId>
						<artifactId>findbugs-maven-plugin</artifactId>
					</plugin>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-checkstyle-plugin</artifactId>
						<configuration>
							<configLocation>static-analysis/checkstyle.xml</configLocation>
							<failsOnError>false</failsOnError>
							<consoleOutput>true</consoleOutput>
						</configuration>
					</plugin>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-pmd-plugin</artifactId>
						<configuration>
							<targetJdk>1.7</targetJdk>
							<rulesets>
								<ruleset>../static-analysis/pmdrules.xml</ruleset>
							</rulesets>
							<excludes>
								<exclude>**/target/generated-sources/**</exclude>
							</excludes>
							<verbose>true</verbose>
						</configuration>
					</plugin>
				</plugins>
			</build>
		</profile>
	</profiles>

</project><file_sep>package com.changer.springaopaspectj_fc;

import com.alibaba.fastjson.JSON;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.math.BigDecimal;

/**
 * Created by fcjiang on 16/4/21.
 */
public class App {
    public static void main(String[] args) {
        System.out.println("我是中文");
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(new String[]{"/springaopaspectj_fc.xml"});
        Person person = (Person) classPathXmlApplicationContext.getBean("person");
        person.setSalary(new BigDecimal("100.122"));
        System.out.println(JSON.toJSONString(person));
    }
}
<file_sep>package com.changer.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Project: AopTest
 * @Author: fcjiang
 * @Date: 2017-02-19
 */
public class JdkProxyFactory implements InvocationHandler {
    private Object targetObject;

    public Object createProxy(Object targetObject) {
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("在invoke方法里, 接下来执行method " + method.getName());
        return method.invoke(targetObject, args);
    }
}
<file_sep>package com.changer.pattern.observer;

import java.text.MessageFormat;
import java.util.Observable;
import java.util.Observer;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-05-17
 */
public class ObserverStudent implements Observer {
    private String name;
    private int score;

    public ObserverStudent() {
    }

    public ObserverStudent(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println(MessageFormat.format("===姓名{0},分数{1}, 接到老师通知{2}", this.name, this.score, ((ObservableTeacher)o).publishNotice()));
    }
}
<file_sep>package com.changer.configs;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @Project: spring-boot-hello
 * @Author: fcjiang
 * @Date: 2016-06-30
 */
@WebFilter(urlPatterns = {"/*"})
public class LogFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("logFilter初始化成功");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        logger.info("step into logFilter");
        filterChain.doFilter(servletRequest, servletResponse);
        logger.info("step out logFilter");
    }

    @Override
    public void destroy() {
        logger.info("logFilter注销完成");
    }
}
<file_sep>package com.changer.daos.entities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by fcjiang on 16/2/1.
 */
public class User {
    private static final Logger logger = LoggerFactory.getLogger(User.class);

    private String name;
    private int age;
    private byte gender;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        logger.info("开始setName name=" + name);
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public byte getGender() {
        return gender;
    }

    public void setGender(byte gender) {
        this.gender = gender;
    }
}
<file_sep>package com.changer.pattern.template;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-07-28
 */
public class ICBCBank extends AbstractBank {
    @Override
    protected String doCalAccountType() {
        System.out.println("ICBCBank's account type is 国有商业银行");
        return "国有商业银行";
    }

    @Override
    protected double doCalInterestRate() {
        System.out.println("ICBCBank's interest rate is 0.01");
        return 0.01;
    }

    @Override
    protected double doGetCapital() {
        System.out.println("ICBCBank's capital is 10000.00");
        return 10000.00;
    }
}
<file_sep>package com.changer.pattern.bridge;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-12-10
 */
public class PNGImage extends Image {
    @Override
    public void parseFile(String fileName) {
        //模拟解析PNG文件并获得一个像素矩阵对象m;
        Matrix m = new Matrix();
        platform.doPaint(m);
        System.out.println(fileName + "，格式为PNG。");
    }
}
<file_sep>package com.changer.properties;

import java.util.Map;

/**
 * @Project: JdkTest
 * @Author: fcjiang
 * @Date: 2016-11-13
 */
public class Demo {
    public static void main(String[] args) {
        String fileName = "/myProperties2.properties";
//        String fileName = "/myProperties1.properties";    // myProperties1不会成功,原因是编译后,这个文件没有被拷贝到target/classes目录下。
        Map<String, String> propertiesMap = new PropertiesReader().getPropertiesMap(fileName);
        for (String key : propertiesMap.keySet()) {
            System.out.println(String.format("key:%s, value:%s", key, (String)propertiesMap.get(key)));
        }
    }
}
<file_sep>package com.changer.service;

import com.changer.util.EnviSettings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * Created by fcjiang on 15/10/31.
 */
@Service
public class LoadSettingsService {
    @Autowired
    private EnviSettings enviSettings;

    @PostConstruct
    public void printSettings(){
        System.out.println(enviSettings);
        System.out.println(enviSettings.getServer());
    }
}
<file_sep>package com.changer.jdkproxy;

import java.math.BigDecimal;

/**
 * @Project: AopTest
 * @Author: fcjiang
 * @Date: 2017-02-19
 */
public class CalMoneyImpl implements ICalMoney {
    @Override
    public BigDecimal multiply(BigDecimal count, BigDecimal price) {
        BigDecimal money = count.multiply(price);
        System.out.println(String.format("money = %s * %s = %s", count.toString(), price.toString(), money.toString()));
        return money;
    }
}
<file_sep>jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/fcjiangDB
jdbc.user=root
jdbc.password=<PASSWORD><file_sep>package com.changer.okio;

import okio.*;

import java.io.File;
import java.io.IOException;

/**
 * @Project: HelloWorld
 * @Author: fcjiang
 * @Date: 2016-05-21
 */
public class App {
    public static void main(String[] args) throws IOException {
        copyFile("/Users/fcjiang/Code/GitHome/examples/HelloWorld/src/main/resources/aa.txt",
                "/Users/fcjiang/Code/GitHome/examples/HelloWorld/src/main/resources/aa-"  + System.currentTimeMillis() + ".txt");
    }

    public static void copyFile(String srcFilePath, String targetFilePath) throws IOException {
//        InputStream inputStream = File.class.getResourceAsStream(srcFilePath);

        Source source = Okio.source(new File(srcFilePath));
        BufferedSource bufferedSource = Okio.buffer(source);

        // todo 如果已经读出来了,则bufferedSource中就没数据了.
//        String content = bufferedSource.readUtf8();
//        System.out.println("conent = " + content);

        Sink sink = Okio.sink(new File(targetFilePath));
        BufferedSink bufferedSink = Okio.buffer(sink);
        bufferedSink.writeAll(bufferedSource);
//        bufferedSink.write(ByteString.encodeUtf8(content));

        // todo 要输出到文件,一定要记录flush
        bufferedSink.flush();
        System.out.println("拷贝完成");
    }
}
<file_sep>## examples from fcjiang

自己学习、备份的一些小Demo。
<file_sep>package com.changer.jvmtest.memoryallocate;

/**
 * 启动参数: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution
 *
 * 指定Heap最小20M,最大20M.其中10M是Eden区(-Xmn10M),剩下的10M是老年代. Eden区是Survivor区的8倍, 8x+2x=10M,算出Eden区8M空间.
 *
 * Created by fcjiang on 16/4/15.
 */
public class BigObjectCreateInOldGenerationxxxx {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3, allocation4;

        allocation1 = new byte[_1MB / 4];

        allocation2 = new byte[4 * _1MB];

        allocation3 = new byte[4 * _1MB];

        allocation3 = null;

        allocation3 = new byte[4 * _1MB];
    }
}
<file_sep>package com.changer.properties;

import com.changer.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * Created by fcjiang on 15/11/25.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@IntegrationTest
@ActiveProfiles("dev")
public class KafkaPropertyTest {
    @Autowired
    KafkaProperty kafkaProperty;

    @Test
    public void testKafkaProperty(){
        System.out.println(kafkaProperty.getName());
        System.out.println(kafkaProperty.getIp());
    }
}
<file_sep>package com.changer.jdkproxy;

import java.math.BigDecimal;

/**
 * @Project: AopTest
 * @Author: fcjiang
 * @Date: 2017-02-19
 */
public class Demo {
    public static void main(String[] args) {
        JdkProxyFactory jdkProxyFactory = new JdkProxyFactory();
        ICalMoney calMoney = (ICalMoney) jdkProxyFactory.createProxy(new CalMoneyImpl());

        BigDecimal count = new BigDecimal("5");
        BigDecimal price = new BigDecimal("8.00");
        BigDecimal result = calMoney.multiply(count, price);
        System.out.printf("计算结果是 " + result.toPlainString());
    }
}
<file_sep>package com.changer.configs;

import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @Project: SpringbootDevTest
 * @Author: fcjiang
 * @Date: 2016-06-29
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public FilterRegistrationBean getFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        filterRegistrationBean.setFilter(characterEncodingFilter);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }
}
<file_sep>package com.changer.service;

import com.changer.model.Person;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by fcjiang on 15/11/17.
 */
@Service
public class PersonService {
    public List<Person> list(){
        List<Person> persons = new ArrayList<>();
        Person person = new Person();
        person.setName("fcjiang");
        person.setAge(20);
        persons.add(person);

        Person person2 = new Person();
        person2.setName("sszhu");
        person2.setAge(18);
        persons.add(person2);

        return persons;
    }
}
<file_sep>http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/

**编写切面类,必须要加注解**```@Aspect```
但不是创建*.aj文件

<file_sep>package com.changer.main;

import com.changer.utils.MyStringUtil;

/**
 * Created by fcjiang on 15/12/24.
 */
public class TestMain {
    public static void main(String[] args) {
        String src = "123x";

        if(MyStringUtil.isNumeric(src)){
            System.out.println("all numerical");
        }
        else {
            System.out.println("not all numerical");
        }

        if(MyStringUtil.isNumeric2(src)){
            System.out.println("all numerical");
        }
        else {
            System.out.println("not all numerical");
        }
    }
}
<file_sep>package com.changer.jvmtest.memoryallocate;

/**
 * 启动参数: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=3145728
 *
 * 指定Heap最小20M,最大20M.其中10M是Eden区(-Xmn10M),剩下的10M是老年代. Eden区是Survivor区的8倍, 8x+2x=10M,算出Eden区8M空间.  PretenureSizeThreshold不能写成M的形式
 *
 * Created by fcjiang on 16/4/15.
 */
public class BigObjectCreateInOldGeneration {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        byte[] allocation;

        allocation = new byte[4 * _1MB];    // 直接在老年代分配

    }
}
<file_sep>package com.changer.dto;

/**
 * Created by fcjiang on 16/3/22.
 */
public class Student extends Person {
    private int score;
    private String schoole;

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public String getSchoole() {
        return schoole;
    }

    public void setSchoole(String schoole) {
        this.schoole = schoole;
    }
}<file_sep>package com.changer.springaopaspectj_fc;

import java.lang.annotation.*;

/**
 * Created by fcjiang on 16/4/21.
 */
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MoneyFormat {
    String value() default "";
}
