Spring注解开发(二)

在这里插入图片描述
在这里插入图片描述

其实总结了一下,前两章都是围绕这个bean标签来展开了,理解了xml,注解使用起来也很简单

一:使用数据源获取连接
<dependencies>
    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.11</version>
    </dependency>
    <!--c3p0-->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
     <!-- Druid连接池 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <!--junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

注:druid连接池也是如下一样使用:DruidDataSource dataSource = new
DruidDataSource();

  • 测试
    @Test
    public void testC3p0() throws Exception {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //设置四大参数
        dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        //从数据源中获取连接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close(); //不是关闭,而是归还给池
    }
此时出现异常:
①Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@5400ff70 -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30). Last acquisition attempt exception: 
②java.sql.SQLException: Unknown system variable 'query_cache_size'	

然后我更改JdbcUrl为:jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&charaterEncoding=utf-8&useSSL=false

此时出现的异常:
②java.sql.SQLException: Unknown system variable 'query_cache_size'

此时在网上查了一下,该异常好像是跟本地安装的mysql版本有关,我查了一下我本地mysql服务器的版本是8.0的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2XfVduM-1596962882219)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1596948712288.png)]

所以我更改pom.xml中的mysql-connector-java的版本为8.0.11,重新测试即可

 <!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>
  • 总结
使用的mysql驱动版本最好和本地Mysql Server Version的版本保持一致!!
注:使用驱动mysql8.0,按道理驱动名应该是com.mysql.cj.jdbc.Driver,但是我使用原始的驱动名
com.mysql.jdbc.Driver测试的时候发现也是ok的!!
优化一:将四大参数抽取到properties配置文件中

将数据库连接的四大参数,放到classpath下的jdbc.properties配置文件中

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&charaterEncoding=utf-8&useSSL=false
jdbc.user=root
jdbc.password=123456
@Test
public void testC3p02() throws Exception {
    //1.创建数据库连接池
    ComboPooledDataSource dataSource = new ComboPooledDataSource();

    //从类路径下获取资源
    ResourceBundle rb = ResourceBundle.getBundle("jdbc");//从classpath下加载jdbc.properties文件,不需要写.properties!!
    String driver = rb.getString("jdbc.driver");
    String jdbcUrl = rb.getString("jdbc.jdbcUrl");
    String user = rb.getString("jdbc.user");
    String password = rb.getString("jdbc.password");

    //3.设置四大参数
    dataSource.setDriverClass(driver);
    dataSource.setJdbcUrl(jdbcUrl);
    dataSource.setUser(user);
    dataSource.setPassword(password);

    //4.从数据源中获取连接
    Connection connection = dataSource.getConnection();
    System.out.println(connection);
}
优化二:使用spring管理连接池对象
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
">

        <context:property-placeholder location="classpath:jdbc.properties"/>

        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="JdbcUrl" value="${jdbc.jdbcUrl}"/>
            <property name="user" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>

</beans>
  • 步骤
1.导入spring-context的jar坐标
2.使用<context:property-placeholder/>必须导入context命名空间,因为是以context标签开头!
3.使用spel,在properties文件中,通过key获取value, 比如${jdbc.user}获取的就是root
  • 小技巧:导入context命名空间!
①context命名空间复制: 
xmlns="http://www.springframework.org/schema/beans"
改成
xmlns:context="http://www.springframework.org/schema/context"
    
②context约束路径复制
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
改成
http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
  • 测试
@Test
    public void testDataSource() throws SQLException {
        ApplicationContext container = new ClassPathXmlApplicationContext("applicationContext.xml");
        ComboPooledDataSource dataSource = (ComboPooledDataSource) container.getBean("dataSource");
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }
二:spring的原始注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zJCKsvPi-1596962882221)(C:\Users\wzj\AppData\Roaming\Typora\typora-user-images\1596952718262.png)]

@Component,@Controller,@Service,@Repository其实作用都是一样的,只不过另外三个更具有语义化

  • 为什么要使用注解呢?

我想配置一个Abean,我还得去xml中写一个bean标签然后各种配置,如果该Abean依赖Bbean,我还得用bean标签把Bbean给配置出来,如果依赖的bean很多,此时xml文件会变得很庞大,从而不好维护,而我使用注解只需@Component就实例化了,使用@Qualifier就自动去容器中寻找依赖,这不是更方便,更简洁吗!!

2.1:演示@Compoent这一类,@Autowired, @Qualifier,@Resource
  • 使用原始xml的方式

注:首先我们得知道三层的依赖关系,Controller层依赖Service层,Service层依赖Dao层

Controller层:

public class UserController {
    public static void main(String[] args) {
        //模拟Controller层,Controller层依赖Servie层
        ApplicationContext container = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) container.getBean("userService");
        userService.save();
    }
}

Service层(接口/实现类):

public interface UserService {
    void save();
}

public class UserServiceImpl implements UserService {

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

    @Override
    public void save() {
        userDao.save();
    }

}

Dao层(接口/实现类):

public interface UserDao {
    void save();
}

public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("save()...");
    }
}

spring中的配置如下:

<bean id="userService" class="com.wzj.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
</bean>

<bean id="userDao" class="com.wzj.dao.impl.UserDaoImpl"></bean>
  • 使用注解的方式

变化的只有实现类而已

//<bean id="userService" class="com.wzj.service.impl.UserServiceImpl">
@Service("userService") //不然默认是将类名首字母小写后,作为id名!
public class UserServiceImpl implements UserService {

    //<property name="userDao" ref="userDao"></property>
    @Autowired //按照类型进行匹配
    @Qualifier("userDao") //按照id名称进行匹配,@Qualifier必须和@Autowired一起使用
    //@Resource(name = "userDao") //@@Resource = @Autowired+@Qualifier 
    private UserDao userDao;

    @Override
    public void save() {
        userDao.save();
    }

}
//<bean id="userDao" class="com.wzj.dao.impl.UserDaoImpl"></bean>, 用以下注解形式代替!
@Repository("userDao") //不然默认是将类名首字母小写后,作为id名!
public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("save()...");
    }
}

spring的配置:只需配置扫描注解

<context:component-scan base-package="com.wzj"/>
  • 总结
1.如果想使用类型注入则使用@Autowired即可 
注:但是如果有多个类型,spring不知道匹配哪个,此时会报异常
2.如果想使用名称注入则使用@Autowired+@Qualifier即可 
注:此时就算有多个类型,也不会报错,因为使用@Qualifier指定了唯一标识
注:@Qualifier必须和@Autowired成对出现
3.@Resource = @AutoWired + @Qualifier
2.2:演示@Value, @Scope, @PostConstruct,@PreDestroy
@Component
@Scope("singleton")
public class User {
    @Value("wzj") //其实这样使用意义不大,直接赋值也是一样的
    private String name;
    @Value("${jdbc.password}") //去spring配置文件中找对应的key,然后把key的值赋值给password变量,这样才是@Value注解的正确使用方式
    private String password;

    public User() {
        System.out.println("User()...");
    }

    @PostConstruct
    public void init(){
        System.out.println("User init()...");
    }

    @PreDestroy
    public void destory(){
        System.out.println("User destory()...");
    }

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

    public static void main(String[] args) {
        ClassPathXmlApplicationContext container = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user1 = (User)container.getBean("user");
        User user2 = (User)container.getBean("user");
        System.out.println(user1 == user2);
        System.out.println(user1);
        container.close();
    }
}
  • 控制台
User()...  因为是单例,所以在加载配置文件的时候就创建了
User init()...
true       因为Scope的值是单例
User{name='wzj', password='123456'} 从jdbc.properties文件中获取的
User destory()... 容器调用close方法
三:spring的新注解

使用之前的原始注解还不能全部替代xml配置文件:如下

  • xml配置文件

使用@Configuration代替

  • 非自定义的Bean的配置:: 比如第三方的jar包中的类,你怎么在类上加@Component?

使用@Bean代替

  • 加载properties文件的配置:context:property-placeholder

使用@PropertySource代替

  • 组件扫描的配置:context:component-scan/

使用@ComponentScan代替

  • 引入其他文件:

使用@Import代替

演示以上注解的效果

1、核心配置类:相当于applicationContext.xml

//标志该类是一个配置类
@Configuration
// <import resource="xxx.xml"/>
@Import({DataSourceConfiguration.class})
// <context:component-scan base-package="com.wzj"/>
@ComponentScan({"com.wzj"})
public class SpringConfiguration {

}

2、配置类:相当于dataSource.xml

//标志该类是一个配置类
@Configuration
// <context:property-placeholder location="classpath:jdbc.properties"/>
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
    @Value("${jdbc.driver}")
    private String driverClass;
    @Value("${jdbc.jdbcUrl}")
    private String jdbcUrl;
    @Value("${jdbc.user}")
    private String user;
    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource") //spring会将当前方法的返回值,以指定名称存储到spring的容器中!
    public ComboPooledDataSource createDataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setUser(user);
        dataSource.setPassword(password);
        return dataSource;
    }

}

3、测试

@Test
public void testAnnotation() throws SQLException {
    AnnotationConfigApplicationContext container = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    User user1 = (User)container.getBean("user");
    User user2 = (User)container.getBean("user");
    System.out.println(user1 == user2);
    System.out.println(user1);
    container.close();
}

4、控制台

User()...  因为是单例,所以在加载配置文件的时候就创建了
User init()...
true       因为Scope的值是单例
User{name='wzj', password='123456'} 从jdbc.properties文件中获取的
User destory()... 容器调用close方法

===和xml方式进行对比=

1、applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
">

    <!--相当于: @Import注解-->
    <import resource="dataSource.xml"/>

    <!--相当于: @ComponentScan注解-->
    <context:component-scan base-package="com.wzj"/>

</beans>

注:没有context命名空间,鼠标放在context那里,idea会帮你创建命名空间和约束的!!

2、dataSource.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--相当于@PropertySource注解-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--相当于@Bean注解-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="JdbcUrl" value="${jdbc.jdbcUrl}"/>
        <property name="user" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

3、测试

@Test
public void test1(){
    ClassPathXmlApplicationContext container = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user1 = (User)container.getBean("user");
        User user2 = (User)container.getBean("user");
        System.out.println(user1 == user2);
        System.out.println(user1);
        container.close();
}

注:结果是一样的

四:spring集成junit
步骤:
导入spring集成Junit的坐标和junit的坐标
使用@Runwith注解替换原来的运行期
使用@ContextConfiguration指定配置文件或配置类
使用@Autowired注入需要测试的对象
创建测试方法进行测试

注:因为spring-context只依赖的如下几个,并没有依赖spring-test的jar包

在这里插入图片描述

<!--junit-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<!--spring集成junit-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

测试如下

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration({"classpath:applicationContext.xml"}) //指定核心配置文件,必须指定classpath
@ContextConfiguration(classes = {SpringConfiguration.class}) //指定自定义的核心配置类
public class SpringJunitTest {

    @Autowired //去spring容器中找User类型的对象,然后赋值给user变量
    private User user;

    @Test
    public void testUser(){
        System.out.println(user);
    }

}

注:来自虽然帅,但是菜的cxy

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值