@Configuration注解:配置Bean
配置Bean就是为了取代配置文件,不用写ApplicationContext.xml了,所以Configuration不会用<context:标签在配置文件中扫描注解@Configuration
@Bean注解是在配置Bean:@Configuration中用来创建对象的
Spring针对复杂对象用FactoryBean来创建
Scope=“”控制对象创建次数
pom.xml:
<?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.itheima</groupId>
<artifactId>spring11</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- 引入事务依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
<!-- junit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
<!--引入log4j日志坐标-->
<!--
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>-->
<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>
<!-- Spring与MyBatis整合依赖需要导入-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
<!--mybatis与spring依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!--连接池依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.18</version>
</dependency>
<!-- 引入mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<!-- 引入mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- 引入动态代理-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
日志文件: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>
User:
package com.baizhiedu.bean;
public class User {
}
ConnectionFactoryBean
package com.baizhiedu.bean;
import org.springframework.beans.factory.FactoryBean;
import java.sql.Connection;
import java.sql.DriverManager;
public class ConnectionFactoryBean implements FactoryBean<Connection> {
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/myBatis?useSSL=false","root","123456");
return conn;
}
@Override
public Class<?> getObjectType() {
return Connection.class;//返回复杂对象的class对象
}
@Override
public boolean isSingleton() {
return false;//控制创建次数,每次都创建新的
}
}
AppConfig:
package com.baizhiedu;
import com.baizhiedu.bean.ConnectionFactoryBean;
import com.baizhiedu.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
@Configuration //@Configuration注解,代表它是一个配置Bean,代替applicationContext.xml
public class AppConfig {
//简单对象
//通过Bean注解创建User对象 user代表原来配置文件的id值 User代表创建对象类型
//方法名字作为默认的id值 如果想要改变可以在@Bean("u") u作为id值
@Bean("u")
@Scope("prototype")//控制对象创建次数,每一次都让spring创建新的对象 prototype创建多次 singleton创建一次
public User user(){
return new User();
}
//复杂对象
/*
Connection 不能直接通过new 创建
Connection 不能直接通过new 创建
*/
@Bean
public Connection conn(){
Connection conn=null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/myBatis?useSSL=false","root","123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//FactoryBean跟@Bean集成
@Bean
public Connection conn1(){
Connection conn = null;//通过方法调用获得复杂对象
try {
ConnectionFactoryBean FactoryBean=new ConnectionFactoryBean();
conn = FactoryBean.getObject();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
}
UserDAO:
package com.baizhiedu.injection;
public interface UserDAO {
public void save();
}
UserDAOImpl:
package com.baizhiedu.injection;
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
System.out.println("UserDAOImpl.save");
}
}
UserService:
package com.baizhiedu.injection;
public interface UserService {
public void register();
}
UserServiceImpl:
package com.baizhiedu.injection;
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
@Override
public void register() {
userDAO.save();
}
}
AppConfig1:
package com.baizhiedu;
import com.baizhiedu.bean.Customer;
import com.baizhiedu.injection.UserDAO;
import com.baizhiedu.injection.UserDAOImpl;
import com.baizhiedu.injection.UserService;
import com.baizhiedu.injection.UserServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration //注解配置Bean
@PropertySource("classpath:/init.properties")//注解读取配置文件,来解下面给JDK类型注入时候的耦合
public class AppConfig1 {
@Value("${id}") //@Value注解为id属性赋值
private Integer id;
@Value("${name}")
private String name;
//自定义类型注入
@Bean
public UserDAO userDAO(){
return new UserDAOImpl();
}
/*@Bean //通过给UserService方法传递一个参数,再进行setUserDAO(userDAO)的注入赋值
public UserService userService(UserDAO userDAO){
UserServiceImpl userService=new UserServiceImpl();
userService.setUserDAO(userDAO);
return userService;
}*/
//第二种注入写法不用传一个参数
@Bean //通过给UserService方法传递一个参数,再进行setUserDAO(userDAO)的注入赋值
public UserService userService(){
UserServiceImpl userService=new UserServiceImpl();
userService.setUserDAO(userDAO());//这里调用userDAO()方法
return userService;
}
// 简单对象,JDK类型注入
@Bean
public Customer customer(){
Customer customer=new Customer();
// customer.setId(1);
// customer.setName("xiaohei");
//通过配置文件,进行注入,来解耦合
customer.setId(id);
customer.setName(name);
return customer;
}
}
init.properties:
id=2 name=suns
TestAnnotation:
package com.baizhiedu;
import com.baizhiedu.bean.Customer;
import com.baizhiedu.bean.User;
import com.baizhiedu.injection.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.sql.Connection;
public class TestAnnotation {
//用于测试:配置Bean
@Test
public void test1(){
//ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);//可以直接指定那个配置Bean的class
ApplicationContext ctx=new AnnotationConfigApplicationContext("com.baizhiedu");//工厂扫描配置com.baizhiedu这个包,查找具有@Configuration注解类型
}
//用于测试:@Bean注解 创建简单对象
@Test
public void test2(){
//ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);//可以直接指定那个配置Bean的class
ApplicationContext ctx=new AnnotationConfigApplicationContext("com.baizhiedu");
User user=(User)ctx.getBean("u");
System.out.println(user);
}
//用于测试:@Bean注解 创建复杂对象
@Test
public void test3(){
//ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);//可以直接指定那个配置Bean的class
ApplicationContext ctx=new AnnotationConfigApplicationContext("com.baizhiedu");
Connection conn=(Connection)ctx.getBean("conn");
System.out.println("conn:"+conn);
}
//用于测试:@Bean注解 创建复杂对象 FactoryBean创建复杂对象和@Bean集成
@Test
public void test4(){
//ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);//可以直接指定那个配置Bean的class
ApplicationContext ctx=new AnnotationConfigApplicationContext("com.baizhiedu");
Connection conn1=(Connection)ctx.getBean("conn1");
System.out.println("conn1:"+conn1);
}
//用于测试:测试User对象的创建次数
@Test
public void test5(){
//ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);//可以直接指定那个配置Bean的class
ApplicationContext ctx=new AnnotationConfigApplicationContext("com.baizhiedu");
User user1=(User)ctx.getBean("u");
User user2=(User)ctx.getBean("u");
System.out.println("user1="+user1);
System.out.println("user2="+user2);
}
//用于测试:@Bean注解:自定义类型注入
@Test
public void test6(){
ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig1.class);//可以直接指定那个配置Bean的class
UserService userService=(UserService)ctx.getBean("userService");
userService.register();
}
//用于测试:@Bean注解:JDK类型注入
@Test
public void test7(){
ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig1.class);//可以直接指定那个配置Bean的class
Customer customer=(Customer)ctx.getBean("customer");
System.out.println("customer="+customer.getId());
System.out.println("customer="+customer.getName());
}
}
test2:
test3:
test4:
test5:注解使用的创建对个对象,所以对象不一样
test6:
t est7:
设置注解扫描:注解
注解排除
注解扫描:
User1:
package com.baizhiedu.scan;
import org.springframework.stereotype.Component;
@Component
public class User1 {
}
User2:
package com.baizhiedu.scan;
import org.springframework.stereotype.Service;
@Service
public class User2 {
}
AppConfig2:
package com.baizhiedu;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Service;
@Configuration //配置Bean注解
//为了扫描曾经讲过的基础注解,使其生效,扫描com.baizhiedu.scan包下的所有注解
@ComponentScan(basePackages = "com.baizhiedu.scan",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class}),
@ComponentScan.Filter(type = FilterType.ASPECTJ,pattern = "*..User1")})//excludeFilters ={}注解排除排除@Service注解
public class AppConfig2 {
}
TestAnnotation2:
package com.baizhiedu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestAnnotation2 {
//用于测试:@ componentScan 扫描基础注解的使用
@Test
public void test1(){
ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig2.class);
String[] beanDefinitionNames=ctx.getBeanDefinitionNames();//获取所有对象的id
for (String beanDefinitionName:beanDefinitionNames){
System.out.println("beanDefinitionName="+beanDefinitionName);
}
}
}
test1:当没有写排除注解是,输出基础注解创建的对象:
当AppConfig2中写上排除注解后:
注解包含:
AppConfig:注释类排除注解,使用包含把@Service注解的对象包含进来
package com.baizhiedu;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Service;
@Configuration //配置Bean注解
//为了扫描曾经讲过的基础注解,使其生效,扫描com.baizhiedu.scan包下的所有注解
/*
注解扫描,注解排除
@ComponentScan(basePackages = "com.baizhiedu.scan",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class}),
@ComponentScan.Filter(type = FilterType.ASPECTJ,pattern = "*..User1")})//excludeFilters ={}注解排除排除@Service注解
*/
/*
注解扫描 注解包含
useDefaultFilters = false,不使用默认扫描,用include-filter扫描方式
*/
@ComponentScan(basePackages = "com.baizhiedu.scan",useDefaultFilters = false,
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})})
public class AppConfig2 {
}
test1: