Spring之Bean学习
时间: 2018-11-27来源:OSCHINA
前景提要
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
简述 :Spring框架主要是涉及到 IOC(控制反转) 和 AOP(切面编程) 两大重点
IOC和DI(依赖注入) 其实就是等同的意思,就是 创建对象和维护对象 ,放在一个容器里,直接依赖注入即可使用
AOP 的存在目的是为了解耦即高内聚,低耦合
Bean 的取值范围
Singleton :一个Spring容器中只有一个Bean的实例,此为Spring的默认配置,全容器共享一个实例
Prototype :每次调用新建一个Bean的实例
Request :Web项目中,给每一个http request新建一个Bean实例
Session :Web项目中,给每一个http session新建一个Bean实例
GlobalSession :这个只在portal应用中有用,给每一个global http session新建一个Bean实例
Bean 的初始化和销毁
1、java配置方式:使用 @Bean 的 initMethod 和 destroyMethod (相当于xml配置的init-method和destory- method)
2、注解方式:利用 JSR-250 的 @PostConstruct 和 @PreDestroy
initMethod和destoryMethod指定BeanWayService类的init和destory方法在构造之后、Bean销毁之前执行
代码及运行结果如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration // 声明当前是配置类
@ComponentScan("com.pkb.prepost") // 自动扫描该包下的所有service、component、repository、controller
public class PrePostConfig
{
// 声明bean实例
@Bean(initMethod = "init", destroyMethod = "destory")
BeanWayService beanWayService()
{
return new BeanWayService();
}
@Bean
JSR250WayService jsr250WayService()
{
return new JSR250WayService();
}
}

public class BeanWayService
{
public void init()
{
System.out.println("@Bean-init-method");
}
public BeanWayService()
{
super();
System.out.println("初始化构造函数-BeanWayService");
}
public void destory()
{
System.out.println("@Bean-destory-method");
}
}
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class JSR250WayService
{
@PostConstruct // 在构造函数执行之后执行
public void init()
{
System.out.println("jsr250-init-method");
}
public JSR250WayService()
{
super();
System.out.println("初始化构造函数-JSR250WayService");
}
@PreDestroy // 在Bean销毁之前执行
public void destroy()
{
System.out.println("jsr250-destroy-method");
}
}

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
PrePostConfig.class);
BeanWayService service = context.getBean(BeanWayService.class);
JSR250WayService service1 = context.getBean(JSR250WayService.class);
context.close();
}
}

spring事件 为 Bean 与 Bean 之间的消息通信提供了支持
1、自定义事件、继承 ApplicationEvent
2、定义事件监听器,实现 ApplicationListener
3、使用容器发布事件
代码及运行结果如下:
import org.springframework.context.ApplicationEvent;

public class DemoEvent extends ApplicationEvent
{
private String msg;
public DemoEvent(Object source, String msg)
{
super(source);
this.msg = msg;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
}

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

// 实现ApplicationListener接口并制定监听的事件类型
@Component
public class DemoListenter implements ApplicationListener<DemoEvent>
{
// 使用onApplicationEvent方法对消息进行接受处理
public void onApplicationEvent(DemoEvent event)
{
String msg = event.getMsg();
System.out.println("我(bean-demoListener)接收到了bean-demoPublisher发布的消息:" + msg);
}
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class DemoPublisher
{
@Autowired
ApplicationContext applicationContext;// 注入applicationContext用来发布事件
// 使用publish方法来发布
public void publish(String msg)
{
applicationContext.publishEvent(new DemoEvent(this, msg));
}
}

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.pkb.event")
public class EventConfig
{}

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
EventConfig.class);
DemoPublisher demoPublisher = context.getBean(DemoPublisher.class);
demoPublisher.publish("hello application event");
context.close();
}
}

Spring Aware 的目的是为了让Bean获得Spring容器的服务,因为 ApplicationContext 接口集成了
MessageSource 接口、 ApplicationEventPublisher 接口和 ResourceLoader 接口, 所以Bean集成了
ApplicationConextAware可以获得Spring容器的所有服务
代码及运行结果如下:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.pkb.aware")
public class AwareConfig
{}

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

// 实现BeanNameAware, ResourceLoaderAware接口,获得Bean名称和资源加载的所有服务
@Service
public class AwareService implements BeanNameAware, ResourceLoaderAware
{
private String beanName;
private ResourceLoader loader;
// 需重写setResourceLoader方法
public void setResourceLoader(ResourceLoader resourceLoader)
{
this.loader = resourceLoader;
}
// 需重写setBeanName方法
public void setBeanName(String beanName)
{
this.beanName = beanName;
}
public void outputResult()
{
System.out.println("Bean的名称为: " + beanName);
Resource resource = loader.getResource("classpath:com/pkb/aware/test.txt");
try
{
System.out.println(
"ResourceLoader加载文件的内容为: " + IOUtils.toString(resource.getInputStream()));
}
catch (Exception e)
{
e.printStackTrace();
}
}
public ResourceLoader getLoader()
{
return loader;
}
public void setLoader(ResourceLoader loader)
{
this.loader = loader;
}
public String getBeanName()
{
return beanName;
}
}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
AwareConfig.class);
AwareService awareService = context.getBean(AwareService.class);
awareService.outputResult();
context.close();
}
}
//在com.pkb.aware包下创建test.txt文件并任意写入内容

spring EL 表达方式
1、注入普通字符
2、注入操作系统属性
3、注入表达式运算结果
4、注入其他Bean的属性
5、注入文件内容
6、注入网址内容
7、注入属性文件
代码及结果如下:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class DemoService
{
@Value("其他类的属性") // 注入普通字符串
private String another;
public String getAnother()
{
return another;
}
public void setAnother(String another)
{
this.another = another;
}
}
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;

@Configuration
@ComponentScan("com.pkb.el")
@PropertySource("classpath:com/pkb/el/test.properties")
public class ElConfig
{
@Value("I Love You!") // 注入普通字符
private String normal;
@Value("#{systemProperties['os.name']}") // 注入操作系统
private String osName;
// 注入表达式结果
@Value("#{T(java.lang.Math).random()*100.0}")
private double randomNumber;
// 注入其他Bean属性
@Value("#{demoService.another}")
private String fromAnother;
// 注入文件资源
@Value("classpath:com/pkb/el/test.txt")
private Resource testFile;
// 注入网址资源
@Value("http://www.baidu.com")
private Resource testUrl;
// 注入配置文件
@Value("${book.name}")
private String bookName;
@Autowired
private Environment environment;
@Bean
public static PropertySourcesPlaceholderConfigurer configurer()
{
return new PropertySourcesPlaceholderConfigurer();
}
public void outputResource()
{
try
{
System.out.println(normal);
System.out.println(osName);
System.out.println(randomNumber);
System.out.println(fromAnother);
System.out.println(IOUtils.toString(testFile.getInputStream()));
System.out.println(IOUtils.toString(testUrl.getInputStream()));
System.out.println(bookName);
System.out.println(environment.getProperty("book.author"));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
ElConfig.class);
ElConfig service = context.getBean(ElConfig.class);
service.outputResource();
context.close();
}
}
//在com.pkb.el包下创建test.properties (book.author = zhangsan
//book.name = spring boot)和 test.txt (内容任意)

Spring 支持 AspectJ 的注解切面编程
1、使用 @Aspect 声明是一个切面
2、使用 @After、@Before、@Around 定义建言( advice ),可直接将拦截规则(切点)作为参数
3、其中 @After、@Before、@Around 参数的拦截规则为切点( PointCut ),为了使切点复用,
可使用 @PointCut 专门定义拦截规则,然后在 @After、@Before、@Around 参数中调用
4、其中符合条件的每一个被拦截处为连接点( JoinPoint )
代码及运行结果如下:
//注解本身没有功能,和xml一样都是一种元数据即解释数据的数据
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
String name();
}
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration // 声明当前类为配置类
@ComponentScan("com.pkb.aop")
@EnableAspectJAutoProxy // 开启spring对AspectJ代理的支持
public class AopConfig
{
}
import org.springframework.stereotype.Service;

@Service
public class DemoAnnotationService
{
@Action(name = "add")
public void add()
{
System.out.println("该方法已被拦截...");
}
}
import org.springframework.stereotype.Service;

@Service
public class DemoMethodService
{
public void add()
{
System.out.println("编写使用方法规则被拦截类...");
}
}
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Aspect // 声明一个切面
@Component // 让此切面成为spring容器管理的bean
public class LogAspect
{
// 声明切点
@Pointcut("@annotation(com.pkb.aop.Action)")
public void annotationPointCut()
{
System.out.println("pointcut方法被调用...");
}
@After("execution(* com.pkb.aop.DemoAnnotationService.*(..))")
public void after(JoinPoint joinPoint)
{
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
System.out.println("注解式拦截 " + action.name());
}
@Before("execution(* com.pkb.aop.DemoMethodService.*(..))")
public void before(JoinPoint joinPoint)
{
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则式拦截 " + method.getName());
}
}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
AopConfig.class);
DemoAnnotationService service = context.getBean(DemoAnnotationService.class);
DemoMethodService service1 = context.getBean(DemoMethodService.class);
service.add();
service1.add();
context.close();
}
}

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

热门排行