Spring基础-高级注解

1、@Configuration注解

Bean注解主要用于替代xml配置,同时也是SpringBoot的核心注解

我们用一段代码来演示,如果用注解来替代我们的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">

    <bean id="user" class="com.wx.annotation.entity.User"></bean>
    <bean id="userDao" class="com.wx.annotation.dao.UserDao"></bean>
    <bean id="userService" class="com.wx.annotation.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>

    <context:component-scan base-package="com.wx.annotation"></context:component-scan>
</beans>

配置类(@Configuration注解的类等价于applicationContext.xml配置文件)

@Configuration
public class AppConfig {
}

工厂的转变

ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
//使用注解后,需要使用下面的工厂
ApplicationContext ctx = new AnnotationConfigApplicationContext("类路径");

日志的替换(不再使用Log4j)

<!--配置Bean的日志logback-->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.25</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jcl-over-slf4j</artifactId>
	<version>1.7.25</version>
</dependency>
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.2.3</version>
</dependency>
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-core</artifactId>
	<version>1.2.3</version>
</dependency>
<dependency>
	<groupId>org.logback-extensions</groupId>
	<artifactId>logback-ext-spring</artifactId>
	<version>0.1.4</version>
</dependency>

logback的配置文件logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 控制台输出 -->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!--格式化输出:%d表示⽇期,%thread表示线程名,
           %-5level:级别从左显示5个字符宽度%msg:⽇志消息,%n是换⾏符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

2、@Bean注解

@Configuration替换了xml配置,那在xml中的<bean>标签,也被我们的@Bean注解给替代了

@Bean注解等价于<bean>标签

2.1、对象的创建

  • 简单对象:直接new
  • 复杂对象:不能直接new,如SqlSessionFactory

所以我们创建简单对象的时候,使用bean注解,一定要是public,返回类型是需要创建对象的类型,方法名等于baen的id值

@Configuration
public class AppConfig {

    @Bean
    public User user(){
        return new User();
    }

    public static void main(String[] args) {
        ApplicationContext ctx
                = new AnnotationConfigApplicationContext(AppConfig.class);
        Object user = ctx.getBean("user");
        System.out.println(user);
    }
}

测试

那如果我们需要创建复杂对象应该如何创建呢?

@Configuration
public class AppConfig {

    @Bean
    public User user(){
        return new User();
    }

    @Bean
    public Connection connection(){
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useSSL=false","root", "root");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    public static void main(String[] args) {
        ApplicationContext ctx
                = new AnnotationConfigApplicationContext(AppConfig.class);
        Object connection = ctx.getBean("connection");
        System.out.println(connection);
    }
}

测试

对于以前的代码,我们创建复杂对象都是通过FactoryBean接口来进行创建的

public class ConnectionFactoryBean implements FactoryBean<Connection> {
    public Connection getObject() throws Exception {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useSSL=false","root","root");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    public Class<?> getObjectType() {
        return Connection.class;
    }

    public boolean isSingleton() {
        return false;
    }
}

那我们现在想要将这个对象通过注解放入到spring中,应该如何操作呢?

@Configuration
public class AppConfig {

    @Bean
    public User user(){
        return new User();
    }

    @Bean
    public Connection connection(){
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useSSL=false","root", "root");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    @Bean
    public Connection connection1() throws Exception {
        Connection connection = new ConnectionFactoryBean().getObject();
        return connection;
    }

    public static void main(String[] args) {
        ApplicationContext ctx
                = new AnnotationConfigApplicationContext(AppConfig.class);
        Object connection = ctx.getBean("connection1");
        System.out.println(connection);
    }
}

测试

可以通过@Bean注解里设置bean的id

@Bean("connection2")
public Connection connection1() throws Exception {
	Connection connection = new ConnectionFactoryBean().getObject();
	return connection;
}

2.2、控制创建次数

使用@Scope注解,singleton单例,prototype多例

@Bean
@Scope("prototype")
public User user(){
	return new User();
}

2.3、注入

@Bean对象如何注入自定义类型的属性呢

以前配置文件的写法

<bean id="userDao" class="com.wx.annotation.dao.UserDao"></bean>
<bean id="userService" class="com.wx.annotation.service.impl.UserServiceImpl">
	<property name="userDao" ref="userDao"></property>
</bean>

使用@Bean注解,注入自定义属性

@Configuration
public class AppConfig {

    @Bean
    public UserServiceImpl userServiceImpl(){
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDao());
        return userService;
    }

    public static void main(String[] args) {
        ApplicationContext ctx
                = new AnnotationConfigApplicationContext(AppConfig.class);
        UserServiceImpl userService = (UserServiceImpl) ctx.getBean("userServiceImpl");
        UserDao userDao = userService.getUserDao();
        System.out.println(userDao);
    }
}

注入JDK类型属性

@Configuration
@PropertySource("classpath:user.properties")
public class AppConfig {
    @Value("${name}")
    private String name;
    @Value("${age}")
    private Integer age;

    @Bean
    @Scope("prototype")
    public User user(){
        User user = new User();
        user.setName(name);
        user.setAge(age);
        return user;
    }
}

这样我们就通过@Bean实现了解耦

3、@ComponentScan注解

我们之前使用配置文件<context:component-scan base-package="com.wx.annotation"></context:component-scan>,

那么我们@ComponentScan注解就是为了替代我们<context:component-scan>标签,@ComponentScan注解就是为了扫描@Service等注解类

@Configuration
@PropertySource("classpath:user.properties")
@ComponentScan(basePackages = "com.wx.annotation")
public class AppConfig {
}

4、优先级

xml配置文件 > @Bean标签 > @Component衍生注解

优先级高的会覆盖优先级低的,主要覆盖的时候,一定要保证id一致。不然得话,容易重复创建bean对象,导致bean冲突

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值